hibernate載入持久化物件的兩種方式——get、load
一.get與load對比
在hibernate中get和load方法是根據id取得持久化物件的兩種方法,但在實際使用的過程中總會把兩者混淆,不知道什麼情況下使用get好,什麼時候使用load方法效率更高。下邊詳細說一下get和load的不同,有些時候為了對比也會把find加進來。
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快取,沒有就建立代理,實際使用資料時才查詢二級快取和資料庫。
二.使用情況分析
至於何種情況使用get什麼時候使用load,我感覺最本質的還是要看要載入的持久化物件及資料量。當要載入的物件與其他物件沒有複雜的聯絡時使用get和load沒有太大的區別;當要載入的物件和其他物件之間有複雜的關聯關係,並且物件之間的關聯數量比較大的情況下使用load方法要比get方法效率高。比如班級和學生兩個持久化物件實體,當取得班級資訊時也要載入對應班級的所有學生資訊,但是如果在程式中我們現在需要的知識班級資訊而不需要學生資訊,在這種情況下get方式要等到班級資訊連同學生資訊都載入完畢才能使用,而load方式會首先載入班級資訊並儲存班級與學生之間的關係,等到真正使用學生資訊的時候才會去載入,所以在關係複雜並且資料量大的情況下load方式要明顯有優勢。
三.簡單總結
總之對於get和load的根本區別,一句話,hibernate對於load方法認為該資料在資料庫中一定存在,可以放心的使用代理來延遲載入,如果在使用過程中發現了問題,只能拋異常;而對於get方法,hibernate一定要獲取到真實的資料,否則返回null。在實際使用過程中如果分不清使用哪一種,直接使用load方式即可。