1. 程式人生 > >hibernate的查詢緩存和二級緩存的配合使用

hibernate的查詢緩存和二級緩存的配合使用

介紹 條件 效果 發現 代碼 spa family 又一 希望

我的上一篇博客Hibernate緩存體系之查詢緩存(query cache),以及list和iterate方法的差別介紹了查詢緩存的概念,以及list和iterate的差別。讀者可能註意到:那篇博客測試的前提是,僅僅開啟查詢緩存,沒有開啟二級緩存。

通過各種情形測試,我們能夠得出一個結論:僅僅開啟查詢緩存。不開啟二級緩存是沒有意義的

為什麽這麽說呢?上一篇博客能夠看出。不開啟二級緩存,iterate()方法存在N+1次數據庫查詢問題,list方法最多僅僅能命中id。也須要N次數據庫查詢,不管是哪兒種情況,查詢緩存已經失去了意義。這篇博客我們開啟二級緩存的情況下。將上篇博客的情況再測試下。看下會是什麽效果。

hibernate4.1.6在hibernate.cfg.xml進行例如以下配置,能夠開啟二級緩存。

<property name="cache.use_second_level_cache">true</property>
<property name="cache.region.factory_class">org.hibernate.cache.EhCacheRegionFactory</property>


因為測試代碼和數據庫都和上篇博客一模一樣。唯一不同就是開啟了二級緩存。這裏不再附代碼。直接通過測試結果來分析結論。


1. 2次list()運行結果分析

testUseList()運行結果例如以下:

Hibernate: 
    select
        student0_.id as id0_,
        student0_.name as name0_,
        student0_.age as age0_ 
    from
        Student student0_ 
    where
        student0_.name=‘zhangsan111‘
list語句測試query cache:[email protected][id=1, name=zhangsan111, age=18]
list語句測試query cache:[email protected]
/* */[id=2, name=zhangsan111, age=18] list語句測試query cache:[email protected][id=3, name=zhangsan111, age=18] -------list進行第二次查詢------ list語句測試query cache:[email protected][id=1, name=zhangsan111, age=18] list語句測試query cache:[email protected][id=2, name=zhangsan111, age=18] list語句測試query cache:[email protected][id=3, name=zhangsan111, age=18]能夠發現list()第一次發出1條sql語句。第二次查詢沒有訪問數據庫,直接從緩存中獲取的數據。在開啟查詢緩存和二級緩存的情況下,list將獲取到的id放入查詢緩存,key是sql語句。將實體對象放入二級緩存,key是實體對象的主鍵值。list會首先依據sql語句去查詢緩存中獲取id,假設沒有獲取到則發出1條sql查詢語句,查詢出全部須要的字段值。


2. 2次iterate()運行結果分析

testUseIterator()運行結果例如以下:

<span style="font-size:14px;">Hibernate: 
    select
        student0_.id as col_0_0_ 
    from
        Student student0_ 
    where
        student0_.name=‘zhangsan111‘
Hibernate: 
    select
        student0_.id as id0_0_,
        student0_.name as name0_0_,
        student0_.age as age0_0_ 
    from
        Student student0_ 
    where
        student0_.id=?
iterate語句測試query cache:[email protected][id=1, name=zhangsan111, age=18]
Hibernate: 
    select
        student0_.id as id0_0_,
        student0_.name as name0_0_,
        student0_.age as age0_0_ 
    from
        Student student0_ 
    where
        student0_.id=?
iterate語句測試query cache:[email protected][id=2, name=zhangsan111, age=18]
Hibernate: 
    select
        student0_.id as id0_0_,
        student0_.name as name0_0_,
        student0_.age as age0_0_ 
    from
        Student student0_ 
    where
        student0_.id=?
iterate語句測試query cache:[email protected][id=3, name=zhangsan111, age=18]
-------iterate進行第二次查詢------
Hibernate: 
    select
        student0_.id as col_0_0_ 
    from
        Student student0_ 
    where
        student0_.name=‘zhangsan111‘
iterate語句測試query cache:[email protected][id=1, name=zhangsan111, age=18]
iterate語句測試query cache:[email protected][id=2, name=zhangsan111, age=18]
iterate語句測試query cache:[email protected][id=3, name=zhangsan111, age=18]</span>
第一次iterate()查詢,因為查詢緩存和二級緩存中都沒有數據,須要進行N+1次數據庫查詢;第二次查詢,僅僅發出一條sql查詢主鍵值,興許依據主鍵值從二級緩存中獲取具體信息。iterate方法會將獲取到的實體對象存入二級緩存。至於是否會將id存入查詢緩存,這裏還不能確定,只是能夠肯定的是。iterate不會利用查詢緩存中的id值。而是每次查詢都又一次使用sql查詢滿足條件的記錄主鍵值。

之後再依據主鍵從二級緩存中查詢實體對象。


3. 先iterate後list運行結果分析

testIteratorAndList1()運行結果例如以下:

<span style="font-size:14px;">Hibernate: 
    select
        student0_.id as col_0_0_ 
    from
        Student student0_ 
    where
        student0_.name=‘zhangsan111‘
Hibernate: 
    select
        student0_.id as id0_0_,
        student0_.name as name0_0_,
        student0_.age as age0_0_ 
    from
        Student student0_ 
    where
        student0_.id=?
iterate語句測試query cache:[email protected][id=1, name=zhangsan111, age=18]
Hibernate: 
    select
        student0_.id as id0_0_,
        student0_.name as name0_0_,
        student0_.age as age0_0_ 
    from
        Student student0_ 
    where
        student0_.id=?
iterate語句測試query cache:[email protected][id=2, name=zhangsan111, age=18]
Hibernate: 
    select
        student0_.id as id0_0_,
        student0_.name as name0_0_,
        student0_.age as age0_0_ 
    from
        Student student0_ 
    where
        student0_.id=?
iterate語句測試query cache:[email protected][id=3, name=zhangsan111, age=18]
-------第一次使用iterate,第二次使用list查詢------
Hibernate: 
    select
        student0_.id as id0_,
        student0_.name as name0_,
        student0_.age as age0_ 
    from
        Student student0_ 
    where
        student0_.name=‘zhangsan111‘
list語句測試query cache:[email protected][id=1, name=zhangsan111, age=18]
list語句測試query cache:[email protected][id=2, name=zhangsan111, age=18]
list語句測試query cache:[email protected][id=3, name=zhangsan111, age=18]</span>
這裏能夠看出,iterate的緩存信息對於list是沒有幫助的。list會發出1條sql。從數據庫中查詢全部須要的字段值。這裏能夠看出:iterate方法不會將主鍵值放到查詢緩存中,由於假設放入查詢緩存的話。這裏的list是沒有必要再發出sql查詢的。


4. 先listiterate運行結果分析

testIteratorAndList2()運行結果例如以下:

<span style="font-size:14px;">Hibernate: 
    select
        student0_.id as id0_,
        student0_.name as name0_,
        student0_.age as age0_ 
    from
        Student student0_ 
    where
        student0_.name=‘zhangsan111‘
list語句測試query cache:[email protected][id=1, name=zhangsan111, age=18]
list語句測試query cache:[email protected][id=2, name=zhangsan111, age=18]
list語句測試query cache:[email protected][id=3, name=zhangsan111, age=18]
-------第一次使用list,第二次使用iterate查詢------
Hibernate: 
    select
        student0_.id as col_0_0_ 
    from
        Student student0_ 
    where
        student0_.name=‘zhangsan111‘
iterate語句測試query cache:[email protected][id=1, name=zhangsan111, age=18]
iterate語句測試query cache:[email protected][id=2, name=zhangsan111, age=18]
iterate語句測試query cache:[email protected][id=3, name=zhangsan111, age=18]</span>
這裏可以得出的結論,跟2次list()查詢幾乎相同。

唯一的區別是:iterate每次查詢都會發出查詢實體對象id的sql語句。


5. 總結

通過開啟查詢緩存和二級緩存,相同的sql查詢可以直接使用查詢緩存中的id和二級緩存中的實體對象,可以有效的降低反復的數據庫查詢,可以提高查詢效率。也就是說:同一時候開啟查詢緩存和二級緩存是有意義的。也是實際使用hibernate的最佳配置。

進一步的。我們也能夠看出list和iterate方法的差別。list()會將實體對象的id放入查詢緩存,將實體對象本身放入二級緩存。iterate不會將實體對象的id放入查詢緩存。可是會將實體對象本身存入二級緩存。

假設第二次查詢可以命中的情況下:list全然不須要查詢數據庫,可以先從查詢緩存中獲取到id。再從二級緩存中獲取實體對象。iterate一定會發出一條查id的sql,然後去二級緩存中獲取實體對象。

至此hibernate的二級緩存、查詢緩存的關系已經講完。list和iterate差別也已經測試出。

希望能對大家有幫助,假設錯誤。歡迎大牛們指正。


hibernate的查詢緩存和二級緩存的配合使用