1. 程式人生 > >Hibernate中session.get()和session.load()的區別

Hibernate中session.get()和session.load()的區別

實際上,兩個方法都是用來從資料庫獲取物件,只不過實現機制不一樣而已。

 

1. session.load()

  • 這種方式總是會返回一個代理而不是真正得去查詢資料庫。 在Hibernate裡面,代理是一個依據ID值獲取到的物件,該物件的屬性還沒有初始化,它看起來就是一個臨時的虛擬物件而已。
  • 如果load方法沒有找到資料,就會丟擲ObjectNotFoundException.

2. session.get()

  • 這種方式總是會去資料庫查詢資料並返回一個真實的物件,該物件就代表資料庫中的一行而非代理。
  • 如果沒有找到資料就會返回null.

效能方面的區別

由於某些原因,Hibernate會建立一些物件,當你做關聯查詢的時候,為了維護物件之間的關係,一般來說你會從資料庫中拿到一個物件(持久化的例項)並把該物件作為一個引用指向另一個物件。我們來看一個例子來讓大家理解什麼情況下我們應該使用session.load().

1. session.get()

拿一個股票的應用來說,股票跟股票交易之間應該是一對多的關係,當你儲存一次股票交易的時候,一般來說我們會寫如下的程式碼:

Stock stock = (Stock)session.get(Stock.class, new Integer(2));
           StockTransaction stockTransactions 
= new StockTransaction(); //set stockTransactions detail stockTransactions.setStock(stock); session.save(stockTransactions);

輸出:

Hibernate:
    select ... from mkyong.stock stock0_
    where stock0_.STOCK_ID=?
Hibernate:
    insert into mkyong.stock_transaction (...)
    values (
?, ?, ?, ?, ?, ?)

用session.get(), Hibernate會查詢資料庫以獲取Stock物件,並把該物件作為一個引用指向StockTransaction物件。然而,儲存流程資料的操作是很耗費資源的,如果一個小時內有成千上萬次股票交易,你認為有必要每次都去查詢資料庫,去首先拿到Stock的真實物件然後把StockTransaction儲存到資料庫中嗎?畢竟來說,你只是需要一個Stock的物件來讓StockTransaction引用而已。

2. session.load()

在上面的應用場景中,session.load()會是一個好的解決方案,讓我們來看一個例子:

Stock stock = (Stock)session.load(Stock.class, new Integer(2));
           StockTransaction stockTransactions = new StockTransaction();
           //set stockTransactions detail
           stockTransactions.setStock(stock);
           session.save(stockTransactions);

輸出:

Hibernate:
    insert into mkyong.stock_transaction (...)
    values (?, ?, ?, ?, ?, ?)

使用session.load()方式,Hibernate不會查詢資料庫(輸出的SQL裡面沒有select語句)來獲取Stock物件,這種方式會返回一個Stock的代理物件 - 一個依據給定的ID值得虛假物件。這這種場景中,一個代理物件就足夠用來儲存股票交易的記錄了。

異常方面的區別

session.load()

tock stock = (Stock)session.load(Stock.class, new Integer(100)); //proxy

 //initialize proxy, no row for id 100, throw ObjectNotFoundException
System.out.println(stock.getStockCode());

oad方法總是會依據給定的ID值來返回一個代理物件,哪怕這個ID值甚至都不存在於資料庫。然而,當Hibernate試圖從資料庫中獲取屬性來初始化該代理物件的時候,它就會使用select語句來從資料庫查詢資料,如果沒有找到任何資料行,就會丟擲ObjectNotFoundException

org.hibernate.ObjectNotFoundException: No row with the given identifier exists:
[com.mkyong.common.Stock#100]

session.get()

//return null if not found
Stock stock = (Stock)session.get(Stock.class, new Integer(100));
System.out.println(stock.getStockCode()); //java.lang.NullPointerException

與load方法不一樣,如果在資料庫中沒有找到資料,get方法會返回null.

總結:

關於這兩個方法的選擇沒有一成不變的解決方案,你必須要首先理解這兩種方法的區別和聯絡,然後才能決定哪種方式更適合你的應用場景。

1. load方法支援延遲載入而get方法則不會。

2. load方法在沒找到資料的時候會丟擲ObjectNotFoundException而get方法則會返回空