Session.load/get方法都可以根據指定的實體類和id從數據庫讀取記錄,並返回與之對應的實體對象。其區別在於:
1. 對於get方法,hibernate會確認一下該id對應的數據是否存在,首先在session緩存中查找,而後在二級緩存中查找,尚未就查詢數據庫,數據庫中沒有就返回null。
2. load方法加載實體對象的時候,根據映射文件上類級別的lazy屬性的配置(默認爲true),分狀況討論:
(1)若爲true,則首先在Session緩存中查找,看看該id對應的對象 是否 存在,不存在則使用延遲加載,返回實體的代理類對象(該代理類爲實體類的子類,由CGLIB動態生成)。等到具體使用該對象(除獲取OID之外)的時候, 再查詢二級緩存和數據庫,若仍沒發現符合條件的記錄,則會拋出一個ObjectNotFoundException。
(2)若爲false,就跟get方法查找順序同樣,只是最終若沒發現符合條件的記錄,則會拋出一個ObjectNotFoundException。
這裏get和load有兩個重要區別:
若是未能發現符合條件的記錄,get方法返回null,而load方法會拋出一個ObjectNotFoundException。
sql
load方法可返回沒有 加載實體數據的代理類實例,而get方法永遠返回有實體數據的對象。(對於load和get方法返回類型:好多書中都說:「get方法永遠只返回實體 類」,實際上並不正確,get方法若是在session緩存中找到了該id對應的對象,若是恰好該對象前面是被代理過的,如被load方法使用過,或者被 其餘關聯對象延遲加載過,那麼返回的仍是原先的代理對象,而不是實體類對象,若是該代理對象尚未加載實體數據(就是id之外的其餘屬性數據),那麼它會 查詢二級緩存或者數據庫來加載數據,可是返回的仍是代理對象,只不過已經加載了實體數據。)數據庫
這句代碼不會去執行數據庫查詢,只有用到user時纔會去執行數據庫查詢。緩存
而:session
則當即去執行數據庫查詢。 因此Users user = (Users)session.load(Users.class, userId);不會執行任何sql。spa
注意:.net
上面這2句代碼,不會去執行數據庫操做。由於load後會在hibernate的一級緩存裏存放一個map對象,該map的key就是userId的值,可是當你getId()時,它會去一級緩存裏拿map的key值,而不去執行數據庫查詢。因此不會報任何錯。不會執行任何數據庫操做。hibernate
而且注意:這兩個方法的第二個參數id,它必須是實現了Java.io.Serializable接口,也就是可序列化的。代理
/** *//**
* load()方法的執行順序以下:
* a):首先經過id在session緩存中查找對象,若是存在此id的對象,直接將其返回
* b):在二級緩存中查找,找到後將 其返回。
* c):若是在session緩存和二級緩存中都找不到此對象,則從數據庫中加載有此ID的對象
* 所以load()方法並不老是致使SQL語句,只有緩存中無此數據時,才向數據庫發送SQL!
*/對象
/** *//**
* 與get()的區別:
* 1:在當即加載對象(當hibernate在從數據庫中取得數據組裝好一個對象後
* 會當即再從數據庫取得數據此對象所關聯的對象)時,若是對象存在,
* load()和get()方法沒有區別,均可以取得已初始化的對象;但若是當對
* 象不存在且是當即加載時,使用get()方法則返回null,而使用load()則
* 拋出一個異常。所以使用load()方法時,要確認查詢的主鍵ID必定是存在
* 的,從這一點講它沒有get方便!
* 2:在延遲加載對象(Hibernate從數據庫中取得數據組裝好一個對象後,
* 不會當即再從數據庫取得數據組裝此對象所關聯的對象,而是等到須要時,
* 都會從數據庫取得數據組裝此對象關聯的對象)時,get()方法仍然使用
* 當即加載的方式發送SQL語句,並獲得已初始化的對象,而load()方法則
* 根本不發送SQL語句,它返回一個代理對象,直到這個對象被訪問時才被
* 初始化。
*/接口
get()----不支持LAZY
load()----支持LAZY