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語句,它返回一個代理對象,直到這個對象被訪問時才被
* 初始化。
*/
性能