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。 

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

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

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

而:

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

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

注意:

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值,而不去執行數據庫查詢。所以不會報任何錯。不會執行任何數據庫操作。

並且注意:這兩個方法的第二個參數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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM