session.load()和session.get()的區別

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之外的其餘屬性數據),那麼它會 查詢二級緩存或者數據庫來加載數據,可是返回的仍是代理對象,只不過已經加載了實體數據。)數據庫

Java代碼 
  1. Users user = (Users)session.load(Users.class, userId);   

這句代碼不會去執行數據庫查詢,只有用到user時纔會去執行數據庫查詢。緩存

而:session

Java代碼
  1. Users user = (Users)session.get(Users.class, userId);    

 則當即去執行數據庫查詢。 因此Users user = (Users)session.load(Users.class, userId);不會執行任何sql。spa

注意:.net

Java代碼
  1. Users user = (Users)session.load(Users.class, userId);     
  2. System.out.println(user.getId());   

上面這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

相關文章
相關標籤/搜索