Hibernate快取原理與查詢快取的組合探究
來源:http://www.javaeye.com/topic/431603
0.前言
由於對Hibernate的二級快取和查詢快取的區別不瞭解,也不知道它們起什麼作用。於是動手做了一些實驗,對它們的組合使用有了一個表面的認識。
1.前提
1) 不使用一級快取(Session級別)的情況。因為大部分api對session的操作都進行n層封裝,用完session就close,一般很少使用到一級快取。
2) 開啟hibernate.show_sql=true,根據sql的是否輸出來判斷是否訪問了資料庫。
2.基礎
2.1.二級快取
二級快取是SessionFactory級別的全域性快取,它為每個類(或集合)提供快取。凡是呼叫二級快取的查詢方法都會從中受益,比如load,list,iterate等方法(注意,get和find不使用快取,直接訪問資料庫)。
開啟條件:
1)hibernate.cache.provider_class=org.hibernate.cache.EhCacheProvider(這裡指定了ehcache)
2)hbm.xml配置<cache usage="read-write"/>
3)ehcache.xml定義該類的cache
簡單地說,二級快取是用來儲存類物件的,並且填充它的所有屬性值。
2.2.查詢快取
查詢快取儲存的是查詢方法(list和iterate等)查詢的sql語句和結果集,跟load這種裝載物件的方法沒有關係。也就是說,使用load方法,查詢快取不理睬。
並且這個結果集只是物件id列表,物件的其他屬性值不儲存。例如,list執行的時候,先根據查詢快取中的sql語句,獲取物件id列表,然後再load(id)來取物件。
開啟條件:
1) hibernate.cache.use_query_cache=true
2)Query或者Criteria使用時,設定setCacheable(true)
簡單地說,查詢快取是用來儲存sql執行後獲取的物件id列表。下一次執行同一條sql時,可直接從查詢快取中獲取到物件id列表。
3.實驗
以下對最常用的load和list方法進行二級快取和查詢快取的組合測試。load和list執行的結果,都是返回同一個物件。
3.1.四種組合
二級快取和查詢快取的組合,根據開啟和不開啟兩種情況,劃分為四種組合(√代表開啟,×代表不開啟):
組合 |
二級快取 |
查詢快取 |
1 |
√ |
× |
2 |
× |
√ |
3 |
√ |
√ |
4 |
× |
× |
3.2.load實驗
對同一個id,使用load執行兩次,觀察sql的輸出現象,也就是判斷第二次load是否訪問了資料庫。其中√代表輸出,×代表未輸出:
組合 |
第一次sql |
第二次sql |
結論 |
1 |
√ |
× |
與查詢快取無關 |
2 |
√ |
√ |
|
3 |
√ |
× |
|
4 |
√ |
√ |
當開啟了二級快取,load先從快取中獲取物件,於是組合1和3的第二次sql都未輸出,即第二次查詢沒有訪問資料庫。
當沒有開啟二級快取,load總是直接訪問資料庫的。也證明了,查詢快取與load方法無關。
3.3.list實驗
對同一條sql語句,使用list執行兩次,觀察sql的輸出現象。其中√代表輸出,×代表未輸出:
組合 |
第一次sql |
第二次sql |
結論 |
1 |
√ |
√ |
list每次訪問資料庫都會填充二級快取,相當於二級快取無效 |
2 |
√ |
√(不一樣) |
這兩條sql語句不一樣,第一條是list的,第二條是load的 |
3 |
√ |
× |
|
4 |
√ |
√ |
對組合1現象的解釋:
當沒有開啟查詢快取時,list每次都會直接訪問資料庫,然後把二級快取給重新填充。也就是說,list在不開啟查詢快取的情況下,根本就沒有利用到二級快取的好處。
對組合2現象的解釋:
第一條sql是list正常訪問資料庫的,但第二次執行list時,由於有了查詢快取,直接根據第一條sql獲取物件的id,此時由於沒有開啟二級快取,load(id)後也沒法從二級快取中拿資料,只好再次訪問資料庫。但在組合3中,load(id)可以從二級快取中拿資料,所以不用訪問資料庫。
3.4.小結
在load和list方法中,使用二級快取和查詢快取的不同組合,效果出現了差別。特別強調的是,由於很多操作是基於list的,如果沒有開啟查詢快取,根本就使用不了二級快取的資料,也就提高不了效能了(但是iterate可以使用到二級快取)。
另外,從表格中可以看出來,同時開啟二級快取和查詢快取,效果是最好的,第二次查詢都不需要訪問資料庫。
4.維護
當存在除hibernate之外的改變資料庫資料的方式時,維護二級快取和查詢快取是很麻煩的。比如使用jdbc或者第三方系統修改了資料庫,hibernate都不知道,也就沒法自行維護快取了。這時需要手動維護,如果存在第三方系統,還需要讓第三方系統發訊息通知hibernate。
維護手段也就是evict(清除某個類的二級快取)和evictQuery(清除查詢快取)。針對資料修改的三種形式,分別維護:
1)insert:evictQuery
2)delete:evict和evictQuery
3)update:evict
一般來講ORM中的快取分為以下幾類:1:事務級快取:即在當前事務範圍內的資料快取. 就Hibernate來講,事務級快取是基於Session的生命週期實現的,每個Session內部會存在一個數據快取,它隨著 Session的建立而存在,隨著Session的銷燬而滅亡,因此也稱為Session Level Cache.
2:應用級快取: 即在某個應用中或應用中某個獨立資料庫訪問子集中的共享快取,此快取可由多個事務共享(資料庫事務或應用事務),事務之間的快取共享策略與應用的事務隔離 機制密切相關.在Hibernate中,應用級快取由SessionFactory實現,所有由一個SessionFactory建立的 Session例項共享此快取,因此也稱為SessionFactory Level Cache.
3:分散式快取:即在多個應用例項,多個JVM間共享的快取策略.分散式快取由多個應用級快取例項組成,通過某種遠端機制(RMI,JMS)實現各個快取例項間的資料同步,任何一個例項的資料修改,將導致整個叢集間的資料狀態同步.
Hibernate的二級快取策略,是針對於ID查詢的快取策略,對於條件查詢則毫無作用。為此,Hibernate提供了針對條件查詢的Query Cache。
查詢快取,快取的key是hql語句,快取的value是滿足hql語句的記錄的主鍵值。也就是說,查詢快取,只是快取資料庫記錄的主鍵值,並不會快取記錄的所有欄位值。
預設hibernate不會開啟查詢快取,這是因為查詢快取只有在hql/hql語句語義完全一致的時候,才能命中。而實際查詢場景下,查詢條件、分頁、 排序等構成的複雜查詢sql語句很難完全一致。可能是hibernate覺得命中率低,所以預設關閉了查詢快取。我們可以根據實際使用情況,決定是否開啟 查詢快取,唯一的原則就是命中率要儘可能的高。如果針對A表的查詢,查詢sql語句基本都是完全一致的情況,就可以針對A使用查詢快取;如果B表的查詢條 件經常變化,很難命中,那麼就不要對B表使用查詢快取。這可能就是hibernate使用查詢快取的時候,既要在hibernate.cfg.xml中進 行配置,也需要query.setCacheable(true)的原因。
查詢快取只對list有用,對iterate方式無用。iterate不會讀也不會寫查詢快取,list會讀也會寫查詢快取。查詢快取中的key是 sql語句(這些sql語句會被hibernate解析,保證語義相同的sql,能夠命中查詢快取),快取的value是記錄的主鍵值
Q:什麼樣的資料適合存放到第二級快取中?
1.很少被修改的資料
2.不是很重要的資料,允許出現偶爾併發的資料
3.不會被併發訪問的資料
4.參考資料,指的是供應用參考的常量資料,它的例項數目有限,它的例項會被許多其他類的例項引用,例項極少或者從來不會被修改。
不適合存放到第二級快取的資料?
1 經常被修改的資料
2 財務資料,絕對不允許出現併發
3 與其他應用共享的資料。
hibernate快取的資料實時性思考?當資料變化時hibernate快取是否能自動更新?
下面是測試例子,經過測試hibernate查詢快取能“監聽”到當前快取實體的資料變化,即當對這個實體進行增加,刪除,修改時,查詢快取將重新去資料庫獲得最新的資料然後再快取起來。
前置配置:
http://www.360doc.com/content/14/0801/16/1073512_398635409.shtml
注意在實體對映檔案中配置:<!--二級快取一般設定為只讀--><cache usage="read-only" />
實驗:返回的是list
測試程式碼:
DAO層的一個方法:
Session session=this.getSession();
//List<TUser> ls=session.createQuery("from TUser where username like '%h%'").setFirstResult(0).setMaxResults(2).list();
List<TUser> ls=session.createQuery("from TUser where username like ? ").setCacheable(true).setParameter(0, "%h%").setFirstResult(0).setMaxResults(30).list();
for (TUser tUser : ls) {
System.out.println(tUser.getUsername()+"=="+tUser.getId());
}
}
junit單元測試的一個方法:
@Test
public void testCache() {
System.out.println("=====第一次讀取=======");
userManager.testCache();
System.out.println("====第二次讀取========");
userManager.testCache();
System.out.println("====新增一個使用者=======");
TUser user=new TUser();
user.setUsername("htt");
user.setPassword("123");
userManager.saveUser(user);
System.out.println("====新增使用者後第一次讀取======");
userManager.testCache();
System.out.println("====新增使用者後第二次讀取======");
userManager.testCache();
System.out.println("====修改使用者=====");
TUser user2=new TUser();
user2.setId("1061");
user2.setUsername("h22");
user2.setPassword("123");
userManager.update(user2);
System.out.println("====修改使用者後第一次讀取======");
userManager.testCache();
System.out.println("====修改使用者後第二次讀取======");
userManager.testCache();
System.out.println("====刪除使用者=====");
TUser user3=new TUser();
user3.setId("1061");
userManager.deleteUser(user3);
System.out.println("====刪除使用者後第一次讀取======");
userManager.testCache();
System.out.println("====刪除使用者後第二次讀取======");
userManager.testCache();
}
場景一:開啟“查詢快取”,關閉二級快取。結果如下
=====第一次讀取=======
Hibernate: select * from ( select tuser0_.ID as ID1_, tuser0_.USERNAME as USERNAME1_, tuser0_.PASSWORD as PASSWORD1_, tuser0_.EMAIL as EMAIL1_, tuser0_.MOBILE as MOBILE1_ from hzc.T_USER tuser0_ where tuser0_.USERNAME like ? ) where rownum <= ?
htt==1081
htt==1087
htt==1086
htt==1084
hcc==1010
hzc==1004
h22==1061
htt==1082
htt==1083
htt==1085
====第二次讀取========
Hibernate: select tuser0_.ID as ID1_0_, tuser0_.USERNAME as USERNAME1_0_, tuser0_.PASSWORD as PASSWORD1_0_, tuser0_.EMAIL as EMAIL1_0_, tuser0_.MOBILE as MOBILE1_0_ from hzc.T_USER tuser0_ where tuser0_.ID=?
Hibernate: select tuser0_.ID as ID1_0_, tuser0_.USERNAME as USERNAME1_0_, tuser0_.PASSWORD as PASSWORD1_0_, tuser0_.EMAIL as EMAIL1_0_, tuser0_.MOBILE as MOBILE1_0_ from hzc.T_USER tuser0_ where tuser0_.ID=?
Hibernate: select tuser0_.ID as ID1_0_, tuser0_.USERNAME as USERNAME1_0_, tuser0_.PASSWORD as PASSWORD1_0_, tuser0_.EMAIL as EMAIL1_0_, tuser0_.MOBILE as MOBILE1_0_ from hzc.T_USER tuser0_ where tuser0_.ID=?
Hibernate: select tuser0_.ID as ID1_0_, tuser0_.USERNAME as USERNAME1_0_, tuser0_.PASSWORD as PASSWORD1_0_, tuser0_.EMAIL as EMAIL1_0_, tuser0_.MOBILE as MOBILE1_0_ from hzc.T_USER tuser0_ where tuser0_.ID=?
Hibernate: select tuser0_.ID as ID1_0_, tuser0_.USERNAME as USERNAME1_0_, tuser0_.PASSWORD as PASSWORD1_0_, tuser0_.EMAIL as EMAIL1_0_, tuser0_.MOBILE as MOBILE1_0_ from hzc.T_USER tuser0_ where tuser0_.ID=?
Hibernate: select tuser0_.ID as ID1_0_, tuser0_.USERNAME as USERNAME1_0_, tuser0_.PASSWORD as PASSWORD1_0_, tuser0_.EMAIL as EMAIL1_0_, tuser0_.MOBILE as MOBILE1_0_ from hzc.T_USER tuser0_ where tuser0_.ID=?
Hibernate: select tuser0_.ID as ID1_0_, tuser0_.USERNAME as USERNAME1_0_, tuser0_.PASSWORD as PASSWORD1_0_, tuser0_.EMAIL as EMAIL1_0_, tuser0_.MOBILE as MOBILE1_0_ from hzc.T_USER tuser0_ where tuser0_.ID=?
Hibernate: select tuser0_.ID as ID1_0_, tuser0_.USERNAME as USERNAME1_0_, tuser0_.PASSWORD as PASSWORD1_0_, tuser0_.EMAIL as EMAIL1_0_, tuser0_.MOBILE as MOBILE1_0_ from hzc.T_USER tuser0_ where tuser0_.ID=?
Hibernate: select tuser0_.ID as ID1_0_, tuser0_.USERNAME as USERNAME1_0_, tuser0_.PASSWORD as PASSWORD1_0_, tuser0_.EMAIL as EMAIL1_0_, tuser0_.MOBILE as MOBILE1_0_ from hzc.T_USER tuser0_ where tuser0_.ID=?
Hibernate: select tuser0_.ID as ID1_0_, tuser0_.USERNAME as USERNAME1_0_, tuser0_.PASSWORD as PASSWORD1_0_, tuser0_.EMAIL as EMAIL1_0_, tuser0_.MOBILE as MOBILE1_0_ from hzc.T_USER tuser0_ where tuser0_.ID=?
htt==1081
htt==1087
htt==1086
htt==1084
hcc==1010
hzc==1004
h22==1061
htt==1082
htt==1083
htt==1085
====新增一個使用者=======
Hibernate: select SEQ_USER.nextval from dual
Hibernate: insert into hzc.T_USER (USERNAME, PASSWORD, EMAIL, MOBILE, ID) values (?, ?, ?, ?, ?)
====新增使用者後第一次讀取======
Hibernate: select * from ( select tuser0_.ID as ID1_, tuser0_.USERNAME as USERNAME1_, tuser0_.PASSWORD as PASSWORD1_, tuser0_.EMAIL as EMAIL1_, tuser0_.MOBILE as MOBILE1_ from hzc.T_USER tuser0_ where tuser0_.USERNAME like ? ) where rownum <= ?
htt==1081
htt==1087
htt==1086
htt==1084
hcc==1010
hzc==1004
h22==1061
htt==1082
htt==1083
htt==1085
htt==1088
====新增使用者後第二次讀取======
Hibernate: select tuser0_.ID as ID1_0_, tuser0_.USERNAME as USERNAME1_0_, tuser0_.PASSWORD as PASSWORD1_0_, tuser0_.EMAIL as EMAIL1_0_, tuser0_.MOBILE as MOBILE1_0_ from hzc.T_USER tuser0_ where tuser0_.ID=?
Hibernate: select tuser0_.ID as ID1_0_, tuser0_.USERNAME as USERNAME1_0_, tuser0_.PASSWORD as PASSWORD1_0_, tuser0_.EMAIL as EMAIL1_0_, tuser0_.MOBILE as MOBILE1_0_ from hzc.T_USER tuser0_ where tuser0_.ID=?
Hibernate: select tuser0_.ID as ID1_0_, tuser0_.USERNAME as USERNAME1_0_, tuser0_.PASSWORD as PASSWORD1_0_, tuser0_.EMAIL as EMAIL1_0_, tuser0_.MOBILE as MOBILE1_0_ from hzc.T_USER tuser0_ where tuser0_.ID=?
Hibernate: select tuser0_.ID as ID1_0_, tuser0_.USERNAME as USERNAME1_0_, tuser0_.PASSWORD as PASSWORD1_0_, tuser0_.EMAIL as EMAIL1_0_, tuser0_.MOBILE as MOBILE1_0_ from hzc.T_USER tuser0_ where tuser0_.ID=?
Hibernate: select tuser0_.ID as ID1_0_, tuser0_.USERNAME as USERNAME1_0_, tuser0_.PASSWORD as PASSWORD1_0_, tuser0_.EMAIL as EMAIL1_0_, tuser0_.MOBILE as MOBILE1_0_ from hzc.T_USER tuser0_ where tuser0_.ID=?
Hibernate: select tuser0_.ID as ID1_0_, tuser0_.USERNAME as USERNAME1_0_, tuser0_.PASSWORD as PASSWORD1_0_, tuser0_.EMAIL as EMAIL1_0_, tuser0_.MOBILE as MOBILE1_0_ from hzc.T_USER tuser0_ where tuser0_.ID=?
Hibernate: select tuser0_.ID as ID1_0_, tuser0_.USERNAME as USERNAME1_0_, tuser0_.PASSWORD as PASSWORD1_0_, tuser0_.EMAIL as EMAIL1_0_, tuser0_.MOBILE as MOBILE1_0_ from hzc.T_USER tuser0_ where tuser0_.ID=?
Hibernate: select tuser0_.ID as ID1_0_, tuser0_.USERNAME as USERNAME1_0_, tuser0_.PASSWORD as PASSWORD1_0_, tuser0_.EMAIL as EMAIL1_0_, tuser0_.MOBILE as MOBILE1_0_ from hzc.T_USER tuser0_ where tuser0_.ID=?
Hibernate: select tuser0_.ID as ID1_0_, tuser0_.USERNAME as USERNAME1_0_, tuser0_.PASSWORD as PASSWORD1_0_, tuser0_.EMAIL as EMAIL1_0_, tuser0_.MOBILE as MOBILE1_0_ from hzc.T_USER tuser0_ where tuser0_.ID=?
Hibernate: select tuser0_.ID as ID1_0_, tuser0_.USERNAME as USERNAME1_0_, tuser0_.PASSWORD as PASSWORD1_0_, tuser0_.EMAIL as EMAIL1_0_, tuser0_.MOBILE as MOBILE1_0_ from hzc.T_USER tuser0_ where tuser0_.ID=?
Hibernate: select tuser0_.ID as ID1_0_, tuser0_.USERNAME as USERNAME1_0_, tuser0_.PASSWORD as PASSWORD1_0_, tuser0_.EMAIL as EMAIL1_0_, tuser0_.MOBILE as MOBILE1_0_ from hzc.T_USER tuser0_ where tuser0_.ID=?
htt==1081
htt==1087
htt==1086
htt==1084
hcc==1010
hzc==1004
h22==1061
htt==1082
htt==1083
htt==1085
htt==1088
====修改使用者=====
Hibernate: update hzc.T_USER set USERNAME=?, PASSWORD=?, EMAIL=?, MOBILE=? where ID=?
====修改使用者後第一次讀取======
Hibernate: select * from ( select tuser0_.ID as ID1_, tuser0_.USERNAME as USERNAME1_, tuser0_.PASSWORD as PASSWORD1_, tuser0_.EMAIL as EMAIL1_, tuser0_.MOBILE as MOBILE1_ from hzc.T_USER tuser0_ where tuser0_.USERNAME like ? ) where rownum <= ?
htt==1081
htt==1087
htt==1086
htt==1084
hcc==1010
hzc==1004
h22==1061
htt==1082
htt==1083
htt==1085
htt==1088
====修改使用者後第二次讀取======
Hibernate: select tuser0_.ID as ID1_0_, tuser0_.USERNAME as USERNAME1_0_, tuser0_.PASSWORD as PASSWORD1_0_, tuser0_.EMAIL as EMAIL1_0_, tuser0_.MOBILE as MOBILE1_0_ from hzc.T_USER tuser0_ where tuser0_.ID=?
Hibernate: select tuser0_.ID as ID1_0_, tuser0_.USERNAME as USERNAME1_0_, tuser0_.PASSWORD as PASSWORD1_0_, tuser0_.EMAIL as EMAIL1_0_, tuser0_.MOBILE as MOBILE1_0_ from hzc.T_USER tuser0_ where tuser0_.ID=?
Hibernate: select tuser0_.ID as ID1_0_, tuser0_.USERNAME as USERNAME1_0_, tuser0_.PASSWORD as PASSWORD1_0_, tuser0_.EMAIL as EMAIL1_0_, tuser0_.MOBILE as MOBILE1_0_ from hzc.T_USER tuser0_ where tuser0_.ID=?
Hibernate: select tuser0_.ID as ID1_0_, tuser0_.USERNAME as USERNAME1_0_, tuser0_.PASSWORD as PASSWORD1_0_, tuser0_.EMAIL as EMAIL1_0_, tuser0_.MOBILE as MOBILE1_0_ from hzc.T_USER tuser0_ where tuser0_.ID=?
Hibernate: select tuser0_.ID as ID1_0_, tuser0_.USERNAME as USERNAME1_0_, tuser0_.PASSWORD as PASSWORD1_0_, tuser0_.EMAIL as EMAIL1_0_, tuser0_.MOBILE as MOBILE1_0_ from hzc.T_USER tuser0_ where tuser0_.ID=?
Hibernate: select tuser0_.ID as ID1_0_, tuser0_.USERNAME as USERNAME1_0_, tuser0_.PASSWORD as PASSWORD1_0_, tuser0_.EMAIL as EMAIL1_0_, tuser0_.MOBILE as MOBILE1_0_ from hzc.T_USER tuser0_ where tuser0_.ID=?
Hibernate: select tuser0_.ID as ID1_0_, tuser0_.USERNAME as USERNAME1_0_, tuser0_.PASSWORD as PASSWORD1_0_, tuser0_.EMAIL as EMAIL1_0_, tuser0_.MOBILE as MOBILE1_0_ from hzc.T_USER tuser0_ where tuser0_.ID=?
Hibernate: select tuser0_.ID as ID1_0_, tuser0_.USERNAME as USERNAME1_0_, tuser0_.PASSWORD as PASSWORD1_0_, tuser0_.EMAIL as EMAIL1_0_, tuser0_.MOBILE as MOBILE1_0_ from hzc.T_USER tuser0_ where tuser0_.ID=?
Hibernate: select tuser0_.ID as ID1_0_, tuser0_.USERNAME as USERNAME1_0_, tuser0_.PASSWORD as PASSWORD1_0_, tuser0_.EMAIL as EMAIL1_0_, tuser0_.MOBILE as MOBILE1_0_ from hzc.T_USER tuser0_ where tuser0_.ID=?
Hibernate: select tuser0_.ID as ID1_0_, tuser0_.USERNAME as USERNAME1_0_, tuser0_.PASSWORD as PASSWORD1_0_, tuser0_.EMAIL as EMAIL1_0_, tuser0_.MOBILE as MOBILE1_0_ from hzc.T_USER tuser0_ where tuser0_.ID=?
Hibernate: select tuser0_.ID as ID1_0_, tuser0_.USERNAME as USERNAME1_0_, tuser0_.PASSWORD as PASSWORD1_0_, tuser0_.EMAIL as EMAIL1_0_, tuser0_.MOBILE as MOBILE1_0_ from hzc.T_USER tuser0_ where tuser0_.ID=?
htt==1081
htt==1087
htt==1086
htt==1084
hcc==1010
hzc==1004
h22==1061
htt==1082
htt==1083
htt==1085
htt==1088
====刪除使用者=====
Hibernate: delete from hzc.T_USER where ID=?
====刪除使用者後第一次讀取======
Hibernate: select * from ( select tuser0_.ID as ID1_, tuser0_.USERNAME as USERNAME1_, tuser0_.PASSWORD as PASSWORD1_, tuser0_.EMAIL as EMAIL1_, tuser0_.MOBILE as MOBILE1_ from hzc.T_USER tuser0_ where tuser0_.USERNAME like ? ) where rownum <= ?
htt==1081
htt==1087
htt==1086
htt==1084
hcc==1010
hzc==1004
htt==1082
htt==1083
htt==1085
htt==1088
====刪除使用者後第二次讀取======
Hibernate: select tuser0_.ID as ID1_0_, tuser0_.USERNAME as USERNAME1_0_, tuser0_.PASSWORD as PASSWORD1_0_, tuser0_.EMAIL as EMAIL1_0_, tuser0_.MOBILE as MOBILE1_0_ from hzc.T_USER tuser0_ where tuser0_.ID=?
Hibernate: select tuser0_.ID as ID1_0_, tuser0_.USERNAME as USERNAME1_0_, tuser0_.PASSWORD as PASSWORD1_0_, tuser0_.EMAIL as EMAIL1_0_, tuser0_.MOBILE as MOBILE1_0_ from hzc.T_USER tuser0_ where tuser0_.ID=?
Hibernate: select tuser0_.ID as ID1_0_, tuser0_.USERNAME as USERNAME1_0_, tuser0_.PASSWORD as PASSWORD1_0_, tuser0_.EMAIL as EMAIL1_0_, tuser0_.MOBILE as MOBILE1_0_ from hzc.T_USER tuser0_ where tuser0_.ID=?
Hibernate: select tuser0_.ID as ID1_0_, tuser0_.USERNAME as USERNAME1_0_, tuser0_.PASSWORD as PASSWORD1_0_, tuser0_.EMAIL as EMAIL1_0_, tuser0_.MOBILE as MOBILE1_0_ from hzc.T_USER tuser0_ where tuser0_.ID=?
Hibernate: select tuser0_.ID as ID1_0_, tuser0_.USERNAME as USERNAME1_0_, tuser0_.PASSWORD as PASSWORD1_0_, tuser0_.EMAIL as EMAIL1_0_, tuser0_.MOBILE as MOBILE1_0_ from hzc.T_USER tuser0_ where tuser0_.ID=?
Hibernate: select tuser0_.ID as ID1_0_, tuser0_.USERNAME as USERNAME1_0_, tuser0_.PASSWORD as PASSWORD1_0_, tuser0_.EMAIL as EMAIL1_0_, tuser0_.MOBILE as MOBILE1_0_ from hzc.T_USER tuser0_ where tuser0_.ID=?
Hibernate: select tuser0_.ID as ID1_0_, tuser0_.USERNAME as USERNAME1_0_, tuser0_.PASSWORD as PASSWORD1_0_, tuser0_.EMAIL as EMAIL1_0_, tuser0_.MOBILE as MOBILE1_0_ from hzc.T_USER tuser0_ where tuser0_.ID=?
Hibernate: select tuser0_.ID as ID1_0_, tuser0_.USERNAME as USERNAME1_0_, tuser0_.PASSWORD as PASSWORD1_0_, tuser0_.EMAIL as EMAIL1_0_, tuser0_.MOBILE as MOBILE1_0_ from hzc.T_USER tuser0_ where tuser0_.ID=?
Hibernate: select tuser0_.ID as ID1_0_, tuser0_.USERNAME as USERNAME1_0_, tuser0_.PASSWORD as PASSWORD1_0_, tuser0_.EMAIL as EMAIL1_0_, tuser0_.MOBILE as MOBILE1_0_ from hzc.T_USER tuser0_ where tuser0_.ID=?
Hibernate: select tuser0_.ID as ID1_0_, tuser0_.USERNAME as USERNAME1_0_, tuser0_.PASSWORD as PASSWORD1_0_, tuser0_.EMAIL as EMAIL1_0_, tuser0_.MOBILE as MOBILE1_0_ from hzc.T_USER tuser0_ where tuser0_.ID=?
htt==1081
htt==1087
htt==1086
htt==1084
hcc==1010
hzc==1004
htt==1082
htt==1083
htt==1085
htt==1088
場景一:開啟“查詢快取”,開啟二級快取。結果如下
log4j:WARN No appenders could be found for logger (org.springframework.test.context.junit4.SpringJUnit4ClassRunner).
log4j:WARN Please initialize the log4j system properly.
SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder".
SLF4J: Defaulting to no-operation (NOP) logger implementation
SLF4J: See http://www.slf4j.org/codes.html#StaticLoggerBinder for further details.
=====第一次讀取=======
Hibernate: select * from ( select tuser0_.ID as ID1_, tuser0_.USERNAME as USERNAME1_, tuser0_.PASSWORD as PASSWORD1_, tuser0_.EMAIL as EMAIL1_, tuser0_.MOBILE as MOBILE1_ from hzc.T_USER tuser0_ where tuser0_.USERNAME like ? ) where rownum <= ?
htt==1081
htt==1087
htt==1086
htt==1084
htt==1089
hcc==1010
hzc==1004
htt==1082
htt==1083
htt==1085
htt==1088
====第二次讀取========
htt==1081
htt==1087
htt==1086
htt==1084
htt==1089
hcc==1010
hzc==1004
htt==1082
htt==1083
htt==1085
htt==1088
====新增一個使用者=======
Hibernate: select SEQ_USER.nextval from dual
Hibernate: insert into hzc.T_USER (USERNAME, PASSWORD, EMAIL, MOBILE, ID) values (?, ?, ?, ?, ?)
====新增使用者後第一次讀取======
Hibernate: select * from ( select tuser0_.ID as ID1_, tuser0_.USERNAME as USERNAME1_, tuser0_.PASSWORD as PASSWORD1_, tuser0_.EMAIL as EMAIL1_, tuser0_.MOBILE as MOBILE1_ from hzc.T_USER tuser0_ where tuser0_.USERNAME like ? ) where rownum <= ?
htt==1081
htt==1087
htt==1086
htt==1084
htt==1089
hcc==1010
hzc==1004
htt==1082
htt==1083
htt==1085
htt==1088
htt==1090
====新增使用者後第二次讀取======
htt==1081
htt==1087
htt==1086
htt==1084
htt==1089
hcc==1010
hzc==1004
htt==1082
htt==1083
htt==1085
htt==1088
htt==1090
====修改使用者=====