Hibernate load和get的區別

get和load方式是根據id取得一個記錄


1. 從返回結果上對比:
load方式檢索不到的話會拋出org.hibernate.ObjectNotFoundException異常
get方法檢索不到的話會返回null


2. 從檢索執行機制上對比:
get方法和find方法直接從數據庫中檢索
load方法
如果映射文件上類級別的lazy屬性爲false:就跟Hibernate get方法查找順序一樣,只是最終若沒發現符合條件的記錄,則會拋出一個ObjectNotFoundException
如果映射文件上類級別的lazy屬性爲true:首先查找session的persistent Context中是否有緩存,如果有則直接返回 如果沒有則判斷是否是lazy,
如果不是直接訪問數據庫檢索,查到記錄返回,查不到拋出異常 如果是lazy則需要建立代理對象,對象的initialized屬性爲false,
target屬性爲null 在訪問獲得的代理對象的屬性時,檢索數據庫,如果找到記錄則把該記錄的對象複製到代理對象的target上,
並將initialized=true,如果找不到就拋出異常。


3. 根本區別說明
如果你使用load方法,hibernate認爲該id對應的對象(數據庫記錄)在數據庫中是一定存在的,所以它可以放心的使用,
它可以放心的使用代理來 延遲加載該對象。在用到對象中的其他屬性數據時才查詢數據庫,但是萬一數據庫中不存在該記錄,
那沒辦法,只能拋異常。所說的load方法拋異常是指在使用 該對象的數據時,數據庫中不存在該數據時拋異常,
而不是在創建這個對象時(注意:這就是由於“延遲加載”在作怪)。


由於session中的緩存對於hibernate來說是個相當廉價的資源,所以在load時會先查一下session緩存看看該id對應的對象是否存在,
不存在則創建代理。所以如果你知道該id在數據庫中一定有對應記錄存在就可以使用load方法來實現延遲加載。


對於get方法,hibernate會確認一下該id對應的數據是否存在,首先在session緩存中查找,然後在二級緩存中查找,還沒有就查數據庫,
數據庫中沒有就返回null。


對於load和get方法返回類型:雖然好多書中都這麼說:“get()永遠只返回實體類”,但實際上這是不正確的,
get方法如果在 session緩存中找到了該id對應的對象,如果剛好該對象前面是被代理過的,如被load方法使用過,
或者被其他關聯對象延遲加載過,那麼返回的還是 原先的代理對象,而不是實體類對象,如果該代理對象還沒有加載實體數據(就是id以外的其他屬性數據),
那麼它會查詢二級緩存或者數據庫來加載數據,但是 返回的還是代理對象,只不過已經加載了實體數據。


get方法首先查詢session緩存,沒有的話查詢二級緩存,最後查詢數據庫;反而load方法創建時首先查詢session緩存,
沒有就創建代理,實際使用數據時才查詢二級緩存和數據庫。


4. 簡單總結


總之對於get和load的根本區別,一句話,hibernate對於load方法認爲該數據在數據庫中一定存在,
可以放心的使用代理來延遲加載,如果在使用過程中發現了問題,只能拋異常;而對於get方法,hibernate一定要獲取到真實的數據,否則返回null。






例子:
Users user = (Users)session.load(Users.class, userId);
Users user = (Users)session.get(Users.class, userId);


加載方法區別:


區別1:如果數據庫中,沒有userId的對象。如果通過get方法加載,則返回的是一個null;如果通過load加載,則返回一個代理對象,
如果後面代碼如果調用user對象的某個屬性(比如user.getPassword())會拋出異常:org.hibernate.ObjectNotFoundException;


區別2:load支持延遲加載,get不支持延遲加載。
也就是說:
Users user = (Users)session.load(Users.class, userId);  
這句代碼不會去執行數據庫查詢,只有用到user時纔會去執行數據庫查詢。
而:
Users user = (Users)session.get(Users.class, userId);  
則立即去執行數據庫查詢。 所以Users user = (Users)session.load(Users.class, userId);不會執行任何sql。




注意:
Java代碼 
Users user = (Users)session.load(Users.class, userId);  
System.out.println(user.getId());  
上面這2句代碼,不會去執行數據庫操作。因爲load後會在hibernate的一級緩存裏存放一個map對象,該map的key就是userId的值,
但是當你getId()時,它會去一級緩存裏拿map的key值,而不去執行數據庫查詢。所以不會報任何錯。不會執行任何數據庫操作。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章