Hibernate中Session.load與Session.get的區別

Session.load/get方法都可以根據指定的實體類和id從數據庫讀取記錄,並返回與之對應的實體對象。數據庫

其區別在於:

若是未能發現符合條件的記錄,get方法返回null,而load方法會拋出一個ObjectNotFoundException。

Load方法可返回實體的代理類實例,而get方法永遠直接返回實體類。

load方法能夠充分利用內部緩存和二級緩存中的現有數據,而get方法則僅僅在內部緩存中進行數據查找,如沒有發現對應數據,將越過二級緩存,直接調用SQL完成數據讀取。

Session在加載實體對象時,將通過的過程:


首先,Hibernate中維持了兩級緩存。第一級緩存由Session實例維護,其中保持了Session當前全部關聯實體的數據,也稱爲內部緩存。而第二級緩存則存在於SessionFactory層次,由當前全部由本SessionFactory構造的Session實例共享。出於性能考慮,避免無謂的數據庫訪問,Session在調用數據庫查詢功能以前,會先在緩存中進行查詢。首先在第一級緩存中,經過實體類型和id進行查找,若是第一級緩存查找命中,且數據狀態合法,則直接返回。

以後,Session會在當前「NonExists」記錄中進行查找,若是「NonExists」記錄中存在一樣的查詢條件,則返回null。「NonExists」記錄了當前Session實例在以前全部查詢操做中,未能查詢到有效數據的查詢條件(至關於一個查詢黑名單列表)。如此一來,若是Session中一個無效的查詢條件重複出現,便可迅速做出判斷,從而得到最佳的性能表現。

對於load方法而言,若是內部緩存中未發現有效數據,則查詢第二級緩存,若是第二級緩存命中,則返回。

如在緩存中未發現有效數據,則發起數據庫查詢操做(Select SQL),如通過查詢未發現對應記錄,則將這次查詢的信息在「NonExists」中加以記錄,並返回null。

根據映射配置和Select SQL獲得的ResultSet,建立對應的數據對象。

將其數據對象歸入當前Session實體管理容器(一級緩存)。

執行Interceptor.onLoad方法(若是有對應的Interceptor)。

將數據對象歸入二級緩存。

若是數據對象實現了LifeCycle接口,則調用數據對象的onLoad方法。

返回數據對象。緩存

 

/** *//**
  * get()方法的執行順序以下:
  * a):首先經過id在session緩存中查找對象,若是存在此id的對象,直接將其返回
  * b):在二級緩存中查找,找到後將 其返回。
  * c):若是在session緩存和二級緩存中都找不到此對象,則從數據庫中加載有此ID的對象
  * 所以get()方法並不老是致使SQL語句,只有緩存中無此數據時,才向數據庫發送SQL!  
  */
session

 /** *//**
  * 與get()的區別:
  * 1:在當即加載對象(當hibernate在從數據庫中取得數據組裝好一個對象後
  * 會當即再從數據庫取得數據此對象所關聯的對象)時,若是對象存在,
  * load()和get()方法沒有區別,均可以取得已初始化的對象;但若是當對
  * 象不存在且是當即加載時,使用get()方法則返回null,而使用load()則
  * 拋出一個異常。所以使用load()方法時,要確認查詢的主鍵ID必定是存在
  * 的,從這一點講它沒有get方便!
  * 2:在延遲加載對象(Hibernate從數據庫中取得數據組裝好一個對象後,
  * 不會當即再從數據庫取得數據組裝此對象所關聯的對象,而是等到須要時,
  * 都會從數據庫取得數據組裝此對象關聯的對象)時,get()方法仍然使用
  * 當即加載的方式發送SQL語句,並獲得已初始化的對象,而load()方法則
  * 根本不發送SQL語句,它返回一個代理對象,直到這個對象被訪問時才被
  * 初始化。
  */

性能

相關文章
相關標籤/搜索