Hibernate中Sessionload/get方法均可以根據指定的實體類和id從數據庫讀取記錄並返回與之對應的實體對象其區別在於
get()方法直接返回實體類load()方法可以返回實體的代理類實例
hibernate load是采用延遲機制(當lazy屬性為true時) 而get不采用延遲機制(get語句馬上讀庫)
找不到符合條件的數據 get方法將返回null
load將會報出ObjectNotFoundExcepion
get支持多態查詢load只有在lazy=false的情況下才支持多態查詢
所謂多態查詢就是可以明確區分加載的是什麼類型的對象load采用代理機制無法支持
延遲加載:Hibernate盡量延遲向數據庫發送sql它自己有一個緩沖區先把sql放在裡面最後一起發送減少網絡開銷和數據庫開銷
load方法原理
當對象hbmxml配置文件元素的lazy屬性設置為true時調用load()方法時則返回持久對象的代理類實例此時的代理類實例是由運行時動態生成的類該代理類實例包括原目標對象的所有屬性和方法該代理類實例的屬性除了ID不為null外所在屬性為null值查看日志並沒有Hibernate SQL輸出說明沒有執行查詢操作當代理類實例通過getXXX()方法獲取屬性值時Hiberante才真正執行數據庫查詢操作
注意
StudentEh s=(StudentEh)sessionload(StudentEhclass);
Systemoutprintln(sgetId());
這兩條語句同樣不會產生sql語句因為sessionload後會在hibernate的一級緩存裡存放一個map對象該map的key就是id的值但是當你getId()時它是從一級緩存裡取map的key值而不去執行數據庫查詢
當對象hbmxml配置文件元素的lazy屬性設置為false時調用load()方法則是立即執行數據庫並直接返回實體類並不返回代理類而調用get()方法時不管lazy為何值都直接返回實體類
get方法原理
get方法hibernate會確認一下該id對應的數據是否存在首先在session緩存中查找然後在二級緩存中查找還沒有就查數據庫數據庫中沒有就返回null
get方法如果在session緩存中找到了該id對應的對象如果剛好該對象前面是被代理過的如被load方法使用過或者被其他關聯對象延遲加載過那麼返回的還是原先的代理對象而不是實體類對象如果該代理對象還沒有加載實體數據(就是id以外的其他屬性數據)那麼它會查詢二級緩存或者數據庫來加載數據但是返回的還是代理對象只不過已經加載了實體數據
總結描述
如果使用load方法hibernate認為該id對應的對象(數據庫記錄)在數據庫中是一定存在的所以它可以放心的使用代理來延遲加載該對象在用到對象中的其他屬性數據時才查詢數據庫但是萬一數據庫中不存在該記錄那沒辦法只能拋異常所說的load方法拋異常是指在使用該對象的數據時數據庫中不存在該數據時拋異常而不是在創建這個對象時由於session中的緩存對於hibernate來說是個相當廉價的資源所以在load時會先查一下session緩存看看該id對應的對象是否存在不存在則創建代理所以如果你知道該id在數據庫中一定有對應記錄存在就可以使用load方法來實現延遲加載
而對於get方法hibernate一定要獲取到真實的數據否則返回null
自己在開發過程中遇到的問題:
我們用MyEclipse hibernate工具通過數據庫生成的DAO類它的findById方法是用的sessionget()方法這是即時獲得pojo對象如果是load方法在執行完load後如果關閉了session那在接下來用到這個pojo對象時就會報session已關閉的錯誤
From:http://tw.wingwit.com/Article/program/Java/ky/201311/28315.html