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方法則會返回空