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)方法:        測試類以下:
相關文章
相關標籤/搜索