問題1:session.flush()調用之後,懶載入還生效嗎? 如果不生效,那是拋異常還是沒有任何反應,或者直接返回null? 答案:生效。可以理解為在同一個session當中,懶載入只會執行一次。 問題2: 多次調用實體類的導航屬性,是否會多次進行sql查詢? 如果session.flush() ...
問題1:session.flush()調用之後,懶載入還生效嗎?
如果不生效,那是拋異常還是沒有任何反應,或者直接返回null?
答案:生效。可以理解為在同一個session當中,懶載入只會執行一次。
問題2: 多次調用實體類的導航屬性,是否會多次進行sql查詢?
如果session.flush()調用之後呢?
答案:不會進行多次sql查詢,即使是在session.flush之後。
問題3:新創建的某個實體類對象,當調用session.flush()之後,能否直接載入其導航屬性?
比如下方的代碼,能否直接從資料庫獲取到ID為roleId的Role對象呢?
User user = new User(......); user.setRoleId(roleId); db.save(user); db.getSession().flush(); Role role = user.getRole();
答案:不能。
問題4:多次調用session.get(Serializable id) 是否會每次都從資料庫查詢?
答案:否,不僅僅是從緩存裡面讀取,而且每次返回的竟然是同一個對象!註意,是同一個記憶體地址哦!
問題5:你知道ID相同的實體類(加了@Entity註解)每次返回的是同一個記憶體對象嗎?
上圖一共執行了3次sql,這個比較好理解,難以理解的是:居然上面3個employee是引用的同一個記憶體地址,也就是說是完完全全一模一樣的同一個對象!比如我把employee1的名字改了,那麼employee2的名字也就改了,真TM surprising!
既然上圖裡面的三個employee是同一個對象,那我們可以猜測那是因為Employee類加了@Entity註解,而這個註解會改變hashcode的值。如果查詢返回一個DTO對象,是不是就應該是不同的對象了吧?馬上就來驗證這個猜測,看下圖:
上圖說明:猜對了。
上圖說明:即使第2個employee是從資料庫查出來的,但是由於它跟第一個employee是同一個記憶體對象,所以它的name屬性已經被改成了記憶體中的那個name值了。神奇吧!
hibernate懶載入天坑:對於ManyToOne註解居然預設是FetchType.EAGER
EAGER是什麼意思呢?比如User類有個role屬性, 當載入user對象的時候,就會同時載入role對象,也就是你期望的只有一條簡單sql從user表查詢,但是卻執行了兩條sql(或者是join查詢)。
所以,通常情況下對於ManyToOne註解,都需要手工設置fetch = FetchType.LAZY,否則會出現嚴重性能問題。
本文中的測試來自jframe 框架
基於spring mvc搭建的多層級多模塊java web應用程式框架。包含:基礎設施層、資料庫定義規範、資料庫訪問規範、日誌記錄規範、多層級異常捕獲、標準ajax規範、母版頁規範、視圖呈現規範、JavaScript框架規範等。實際上該框架定義的規範極其詳細,比如資料庫定義層:枚舉類使用規範、datetime/bool/string欄位規範、1對1、1對多、多對1、多對多外鍵關係映射規範、父類定義規範、欄位註釋規範、懶載入規範等等。。。
技術交流QQ群:651499479,歡迎java大神指點迷津,也歡迎新手進群學習。
github地址: https://github.com/leotsai/jframe
THE END.