Hibernate的緩存機制(二)

package org.qiujy.test.cache;

import java.util.List;

import org.hibernate.HibernateException;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.qiujy.common.HibernateSessionFactory;
import org.qiujy.domain.cachedemo.Product;

public class TessQueryCache {

             public static void main(String[] args) {
                            Session session = HibernateSessionFactory.getSession();
                            Transaction tx =null;
                            
                            try{
                                         tx = session.beginTransaction();
                                         Query query = session.createQuery("from Product");
                                         //激活查詢緩存
                                         query.setCacheable(true);
                                         //使用自定義的查詢緩存區域,若不設置,則使用標準查詢緩存區域
                                         query.setCacheRegion("myCacheRegion");
                                        
                                         List list = query.list();
                                         for(int i = 0 ; i < list.size(); i++){
                                                        Product prod = (Product)list.get(i);
                                                        System.out.println(prod.getName());
                                         }
                                        
                                        tx.commit();
                            }catch(HibernateException e){
                                         if(tx != null){
                                                        tx.rollback();
                                         }
                                         e.printStackTrace();
                            }finally{
                                         HibernateSessionFactory.closeSession();
                            }
             }
}

<many-to-one name="category"
                                column="categoryId"
                             class="org.qiujy.domain.cachedemo.Category"
                             cascade="save-update"
                                not-null="true">
                </many-to-one>
            
        </class>

</hibernate-mapping>

2)      編輯ehcache.xml文件:
<ehcache>
        <diskStore path="c:\\ehcache\"/>
        <defaultCache
                maxElementsInMemory="10000"
                eternal="false"
                timeToIdleSeconds="120"
                timeToLiveSeconds="120"
                overflowToDisk="true"    
                />
                
        <!-- 設置Category類的緩存的數據過期策略 -->
        <cache name="org.qiujy.domain.cachedemo.Category"
                maxElementsInMemory="100"
                eternal="true"
                timeToIdleSeconds="0"
                timeToLiveSeconds="0"
                overflowToDisk="false"
                />
                
         <!-- 設置Category類的products集合的緩存的數據過期策略 -->
         <cache name="org.qiujy.domain.cachedemo.Category.products"
                maxElementsInMemory="500"
                eternal="false"
                timeToIdleSeconds="300"
                timeToLiveSeconds="600"
                overflowToDisk="true"
                />
                
        <cache name="org.qiujy.domain.cachedemo.Product"
                maxElementsInMemory="500"
                eternal="false"
                timeToIdleSeconds="300"
                timeToLiveSeconds="600"
                overflowToDisk="true"
                />
        
</ehcache>
配置的元素說明:
元素或屬性 描述
<diskStore> 設置緩存數據文件的存放目錄
<defaultCache> 設置緩存的默認數據過期策略
<cache> 設定具體的命名緩存的數據過期策略
每個命名緩存代表一個緩存區域,每個緩存區域有各自的數據過期策略。命名緩存機制使得用戶能夠在每個類以及類的每個集合的粒度上設置數據過期策略。
cache元素的屬性 
name 設置緩存的名字,它的取值爲類的全限定名或類的集合的名字
maxInMemory 設置基於內存的緩存中可存放的對象最大數目
eternal 設置對象是否爲永久的,true表示永不過期,此時將忽略timeToIdleSeconds和timeToLiveSeconds屬性;
默認值是false
timeToIdleSeconds 設置對象空閒最長時間,超過這個時間,對象過期。當對象過期時,EHCache會把它從緩存中清除。
如果此值爲0,表示對象可以無限期地處於空閒狀態。
timeToLiveSeconds 設置對象生存最長時間,超過這個時間,對象過期。
如果此值爲0,表示對象可以無限期地存在於緩存中。
overflowToDisk 設置基於內在的緩存中的對象數目達到上限後,是否把溢出的對象寫到基於硬盤的緩存中

3)      寫一測試類:
package org.qiujy.test.cache;

import java.util.List;

import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.qiujy.common.HibernateSessionFactory;
import org.qiujy.domain.cachedemo.Product;

public class TestCache {

             public static void main(String[] args) {
                
                            //test cache.........
                            Session session2 = HibernateSessionFactory.getSession();
                            Transaction tx2 =null;
                            
                            try{
                                         tx2 = session2.beginTransaction();
                                        
                                         List list = session2.createQuery("from Product").list();
                                        
                                         for(int i = 0 ; i < list.size(); i++){
                                                        Product prod = (Product)list.get(i);
                                                        System.out.println(prod.getName());
                                         }
                                        
                                        tx2.commit();
                            }catch(HibernateException e){
                                         if(tx2 != null){
                                                        tx2.rollback();
                                         }
                                         e.printStackTrace();
                            }finally{
                                         HibernateSessionFactory.closeSession();
                            }
                            
                            //-------------------
                            Session session3 = HibernateSessionFactory.getSession();
                            Transaction tx3 =null;
                            
                            try{
                                         tx3 = session3.beginTransaction();
                                        
                                         Product prod = (Product)session3.get(Product.class, new Long(1));
                                         System.out.println("從cache中得到,不執行SQL---" + prod.getName());
                                    
                                        tx3.commit();
                            }catch(HibernateException e){
                                         if(tx3 != null){
                                                        tx3.rollback();
                                         }
                                         e.printStackTrace();
                            }finally{
                                         HibernateSessionFactory.closeSession();
                            }
             }
}

首先數據庫插入1000條產品記錄和1條類別記錄。此1000個產品都屬於這一類別。然後執行以上測試類,在Session2中查詢所有的產品,輸出它的產品名,Session2會把這些數據加載到二級緩存中,由於有1000個對象,而配置中定義內存中只能存放500個,剩下的對象就會寫到指定的磁盤目錄中緩存起來。所以在磁盤相應位置可看到數據文件:
5.    查詢緩存(Query Cache):
對於經常使用的查詢語句,如果啓用了查詢緩存,當第一次執行查詢語句時,Hibernate會把查詢結果存放在第二緩存中。以後再次執行該查詢語句時,只需從緩存中獲得查詢結果,從而提高查詢性能。
1.      查詢緩存適用於以下場合:
l 在應用程序運行時經常使用的查詢語句。
l 很少對與查詢語句關聯的數據庫數據進行插入、刪除或更新操作。
2.      Hibernate的Query緩存策略的過程如下:
1) Hibernate首先根據這些信息組成一個Query Key,Query Key包括條件查詢的請求一般信息:SQL, SQL需要的參數,記錄範圍(起始位置rowStart,最大記錄個數maxRows),等。
2) Hibernate根據這個Query Key到Query緩存中查找對應的結果列表。如果存在,那麼返回這個結果列表;如果不存在,查詢數據庫,獲取結果列表,把整個結果列表根據Query Key放入到Query緩存中。
3) Query Key中的SQL涉及到一些表名,如果這些表的任何數據發生修改、刪除、增加等操作,這些相關的Query Key都要從緩存中清空。
只有當經常使用同樣的參數進行查詢時,這纔會有些用處。
啓用查詢緩存的步驟:
1)      配置二級緩存:
Hibernate提供了三種和查詢相關的緩存區域:
l 默認的查詢緩存區域:org.hibernate.cache.StandardQueryCache
l 用戶自定義的查詢緩存區域:
l 時間戳緩存區域:org.hibernate.cache.UpdateTimestampCache
默認的查詢緩存區域以及用戶自定義的查詢緩存區域都用於存放查詢結果。而時間戳緩存區域存放了對與查詢結果相關的表進行插入、更新或刪除操作的時間戳。Hibernate通過時間戳緩存區域來判斷被緩存的查詢結果是否過期。所以,當應用程序對數據庫的相關數據做了修改,Hibernate會自動刷新緩存的查詢結果。但是如果其他應用程序對數據庫的相關數據做了修改,則無法監測,此時必須由應用程序負責監測這一變化,然後手工刷新查詢結果。Query接口的setForceCacheRefresh(true)可以手工刷新查詢結果。
在ehcache.xml中添加如下配置:
<!-- 設置默認的查詢緩存的數據過期策略 -->
 
     <cache name="org.hibernate.cache.StandardQueryCache"
             maxElementsInMemory="50"
             eternal="false"
             timeToIdleSeconds="3600"
             timeToLiveSeconds="7200"
             overflowToDisk="true"/>
                
        <!-- 設置時間戳緩存的數據過期策略 -->
        <cache name="org.hibernate.cache.UpdateTimestampsCache"
             maxElementsInMemory="5000"
             eternal="true"
             overflowToDisk="true"/>
        
        <!-- 設置自定義命名查詢緩存customerQueries的數據過期策略 -->
        <cache name="myCacheRegion"
                maxElementsInMemory="1000"
                eternal="false"
                timeToIdleSeconds="300"
                timeToLiveSeconds="600"
                overflowToDisk="true"
                />

2)      打開查詢緩存:在hibernate.cfg.xml添加如下配置
<!--啓用查詢緩存 -->
<property name="cache.use_query_cache">true</property>

3)      在程序中使用:
雖然按以上設置好了查詢緩存,但Hibernate在執行查詢語句語句時仍不會啓用查詢緩存。對於希望啓用查詢緩存的查詢語句,應該調用Query接口的setCacheeable(true)方法:
       測試類如下:
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章