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)方法:        测试类以下:
相关文章
相关标签/搜索