天天看點

hiberante中get和load方法的差別

1.從傳回結果上對比:

load方式檢索不到的話會抛出org.hibernate.ObjectNotFoundException異常

get方法檢索不到的話會傳回null

2.從檢索執行機制上對比: get方法和find方法都是直接從資料庫中檢索 而load方法的執行則比較複雜首先查找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。