程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> JAVA編程 >> 關於JAVA >> Hibernate中load和get的區別

Hibernate中load和get的區別

編輯:關於JAVA

Hibernate中Session.load/get方法均可以根據指定的實體類和id從數據庫讀取記錄,並返回與之對應的實體對象。其區別在於:

1.get()方法直接返回實體類,load()方法可以返回實體的代理類實例。

2.hibernate load是采用延遲機制(當lazy屬性為true時) 而get不采用延遲機制(get語句馬上讀庫)

3.找不到符合條件的數據 get方法將返回null

load將會報出ObjectNotFoundExcepion

4.get支持多態查詢,load只有在lazy=false的情況下才支持多態查詢

所謂多態查詢,就是可以明確區分加載的是什麼類型的對象,load采用代理機制無法支持

延遲加載:Hibernate盡量延遲向數據庫發送sql,它自己有一個緩沖區,先把sql放在裡面,最後一起發送,減少網絡開銷和數據庫開銷。

load方法原理:

當對象.hbm.xml配置文件元素的lazy屬性設置為true時,調用load()方法時則返回持久對象的代理類實例,此時的代理類實例是由運行時動態生成的類,該代理類實例包括原目標對象的所有屬性和方法,該代理類實例的屬性除了ID不為null外,所在屬性為null值,查看日志並沒有Hibernate SQL輸出,說明沒有執行查詢操作,當代理類實例通過getXXX()方法獲取屬性值時,Hiberante才真正執行數據庫查詢操作。

注意:

01.StudentEh s=(StudentEh)session.load(StudentEh.class,10);
02.
03.System.out.println(s.getId());

這兩條語句同樣不會產生sql語句,因為session.load後會在hibernate的一級緩存裡存放一個map對象,該map的key就是id的值,但是當你getId()時,它是從一級緩存裡取map的key值,而不去執行數據庫查詢。

當對象.hbm.xml配置文件元素的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方法是用的session.get()方法,這是即時獲得pojo對象,如果是load方法,在執行完load後如果關閉了session,那在接下來用到這個pojo對象時就會報session已關閉的錯誤。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved