文章出處

 問題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.


文章列表


不含病毒。www.avast.com
arrow
arrow
    全站熱搜

    大師兄 發表在 痞客邦 留言(0) 人氣()