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


-- 翻譯自https://www.mkyong.com/hibernate/different-between-session-get-and-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()

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

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

load方法總是會依據給定的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.

總結:

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

 

PS:第一次翻譯國外網站的文章,感覺真是費力,本人英語水平有限,還請各位多多諒解。其實關於session.get()和session.load()的區別,只要記住兩點就好了:

1. load方法支持延遲加載而get方法則不會。

2. load方法在沒找到數據的時候會拋出ObjectNotFoundException而get方法則會返回空


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM