ehcache-----在spring和hibernate下管理ehcache和query cache

1. 在Hibernate配置文件中设置:

 

<!-- Hibernate SessionFactory -->
    <bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
        <property name="dataSource" ref="dataSource"/>
        <property name="mappingResources">
        <list>
            <value>com/ouou/model/Videos.hbm.xml</value>   
         </list>
         </property>
        <property name="hibernateProperties">
            <props>
                <prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
                <prop key="hibernate.current_session_context_class">thread</prop>
                <prop key="hibernate.cglib.use_reflection_optimizer">false</prop>
                <prop key="hibernate.query.substitutions">true 'Y', false 'N'</prop>
                <!--add ehcache-->
                <prop key="hibernate.cache.provider_class">org.hibernate.cache.EhCacheProvider</prop>
                <prop key="hibernate.cache.use_query_cache">false</prop><!-- 是否使用查询缓存 -->
                <!--
                <prop key="hibernate.cache.provider_configuration_file_resource_path">/ehcache.xml</prop>
                <prop key="hibernate.show_sql">true</prop>
                -->
                <!--<prop key="hibernate.transaction.auto_close_session">true</prop>-->
                <prop key="connection.provider_class">org.hibernate.connection.C3P0ConnectionProvider</prop>
                <!-- Create/update the database tables automatically when the JVM starts up
                 <prop key="hibernate.hbm2ddl.auto">update</prop> -->
                <!-- Turn batching off for better error messages under PostgreSQL -->
                <prop key="hibernate.jdbc.batch_size">25</prop>
                <!--
                <prop key="hibernate.connection.pool_size">10</prop>
                -->
            </props>
        </property>
    </bean>

 

如果不设置“查询缓存”,那么hibernate只会缓存使用load()方法获得的单个持久化对象,如果想缓存使用findall()、 list()、Iterator()、createCriteria()、createQuery()等方法获得的数据结果集的话,就需要设置 hibernate.cache.use_query_cache true 才行

2.首先设置EhCache,建立配置文件ehcache.xml,默认的位置在class-path,可以放到你的src目录下:

<ehcache>

    <!-- Sets the path to the directory where cache .data files are created.

     If the path is a Java System Property it is replaced by
     its value in the running VM.
     The following properties are translated:
     user.home - User's home directory
     user.dir - User's current working directory
     java.io.tmpdir - Default temp file path -->
     <!--<diskStore path="java.io.tmpdir"/>-->
     <diskStore path="/data/ehcache"/>

    <!--Default Cache configuration. These will applied to caches programmatically created through
        the CacheManager.

        The following attributes are required:

        maxElementsInMemory            - Sets the maximum number of objects that will be created in memory
        eternal                                     - Sets whether elements are eternal. If eternal,  timeouts are 
                                                            ignored and the element is never expired.
        overflowToDisk                      - Sets whether elements can overflow to disk when the in-memory cache
                                                        has reached the maxInMemory limit.

        The following attributes are optional:
        timeToIdleSeconds            - Sets the time to idle for an element before it expires.
                                                        i.e. The maximum amount of time between accesses before an
                                                        element expires Is only used if the element is not eternal.
                                                        Optional attribute. A value of 0 means that an Element can idle
                                                        for infinity.The default value is 0.
        timeToLiveSeconds              - Sets the time to live for an element before it expires.
                                                         i.e. The maximum time between creation time and when an element 
                                                         expires.  Is only used if the element is not eternal.
                                                         Optional attribute. A value of 0 means that and Element can live
                                                         for infinity.
                                                        The default value is 0.
        diskPersistent                           - Whether the disk store persists between restarts of the Virtual
                                                             Machine.
                                                         The default value is false.
        diskExpiryThreadIntervalSeconds   - The number of seconds between runs of the disk expiry thread. 
                                                         The default value  is 120 seconds.
        -->

    <defaultCache
        maxElementsInMemory="10000"
        eternal="false"
        overflowToDisk="true"
        timeToIdleSeconds="120"
        timeToLiveSeconds="120"
        diskPersistent="false"
        diskExpiryThreadIntervalSeconds="120"/>
    <cache name="org.hibernate.cache.UpdateTimestampsCache" maxElementsInMemory="5000" 
     eternal="true" overflowToDisk="true"/>

<cache name="org.hibernate.cache.StandardQueryCache" maxElementsInMemory="5" eternal="false" timeToLiveSeconds="120" overflowToDisk="true"/>

<cache name="userCache" maxElementsInMemory="100000" eternal="false" timeToIdleSeconds= "600" timeToLiveSeconds="600" overflowToDisk="false" diskPersistent="false"/>

<cache name="com.ouou.webapp.util.OuouMethodIntecepter" maxElementsInMemory="100000" eternal="false" timeToIdleSeconds="600" timeToLiveSeconds="600" overflowToDisk="false" diskPersistent="false"/>

<cache name="bbcode" maxElementsInMemory="100000" eternal="false" timeToIdleSeconds="600" timeToLiveSeconds="600" overflowToDisk="false" diskPersistent="false"/>

<cache name="com.ouou.model.Videos" maxElementsInMemory="10000" eternal="false" overflowToDisk="false" timeToIdleSeconds="120" timeToLiveSeconds="120" diskPersistent="false"/>

<cache name="com.ouou.model.Tags" maxElementsInMemory="10000" eternal="false" overflowToDisk="false" timeToIdleSeconds="120" timeToLiveSeconds="120" diskPersistent="false"/>

</ehcache>

 

以com.ouou.model.Videos为例子
在Videos.hbm.xml中配置:
<class name="Videos" table="TEST" lazy="false">
  <cache usage="read-write" region="ehcache.xml中的name的属性值"/>注意:这一句需要紧跟在class标签下面,其他位置无效。
hbm文件查找cache方法名的策略:如果不指定hbm文件中的region="ehcache.xml中的name的属性值",则使用name名为com.ouou.model.Videos的cache,
如果不存在与类名匹配的cache名称,则用defaultCache。
如果Videos包含set集合,则需要另行指定其cache
例如Videos包含Tags集合,则需要

 

添加如下配置到ehcache.xml中

<cache name="com.ouou.model.Tags"
        maxElementsInMemory="10000" eternal="false" timeToIdleSeconds="120"
        timeToLiveSeconds="120" overflowToDisk="false" />

 


另,针对查询缓存的配置如下:

<cache name="org.hibernate.cache.UpdateTimestampsCache"
        maxElementsInMemory="5000"
        eternal="true"
        overflowToDisk="true"/>
<cache name="org.hibernate.cache.StandardQueryCache"
        maxElementsInMemory="10000"
        eternal="false"
        timeToLiveSeconds="120"
        overflowToDisk="true"/>

 



3、 选择缓存策略依据:

<cache  usage="transactional|read-write|nonstrict-read-write|read-only" (1)/>
ehcache不支持transactional,其他三种可以支持。


read-only:无需修改, 那么就可以对其进行只读 缓存,注意,在此策略下,如果直接修改数据库,即使能够看到前台显示效果,
但是将对象修改至cache中会报error,cache不会发生作用。另:删除记录会报错,因为不能在read-only模式的对象从cache中删除。
read-write:需要更新数据,那么使用读/写缓存 比较合适,前提:数据库不可以为serializable transaction isolation level
(序列化事务隔离级别)
nonstrict-read-write:只偶尔需要更新数据(也就是说,两个事务同时更新同一记录的情况很不常见),也不需要十分严格的事务隔离,
那么比较适合使用非严格读/写缓存策略。

4、 调试时候使用log4j的log4j.logger.org.hibernate.cache=debug,更方便看到ehcache的操作过程,主要用于调试过程,实际应用发布时候,请注释掉,以免影响性能。

 

5、 使用ehcache,打印sql语句是正常的,因为query cache设置为true将会创建两个缓存区域:一个用于保存查询结果集 (
org.hibernate.cache.StandardQueryCache);另一个则用于保存最近查询的一系列表的时间戳(org.hibernate.cache.UpdateTimestampsCache)。
请注意:在查询缓存中,它并不缓存结果集中所包含的实体的确切状态;它只缓存这些实体的标识符属性的值、以及各值类型的结果。
需要将打印sql语句与最近的cache内容相比较,将不同之处修改到cache中,所以查询缓存通常会和二级缓存一起使用。

 

 



番外

Hibernate的Query缓存策略 

 

启用查询缓存的步骤:

1) 配置二级缓存:

Hibernate提供了三种和查询相关的缓存区域:

· 默认的查询缓存区域:org.hibernate.cache.StandardQueryCache

· 时间戳缓存区域: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添加如下配置,由于查询缓存查询命中率比较低(Hibernate的自身机制造成),所以Hibernate的缺省值是:关闭,所以在使用查询缓存时要打开该缓存。

<!--启用查询缓存 -->

<property name="cache.use_query_cache">true</property> 

3)在程序中使用:

虽然按以上设置好了查询缓存,但Hibernate在执行查询语句语句时仍不会启用查询缓存。对于希望启用查询缓存的查询语句,应该调用Query接口的setCacheeable(true)方法:

测试类如下:

/**

 *  演示查询缓存

 */

public void queryCache()

{

// 创建Session对象

Session session = sf.openSession();

// 创建HQL语句

String hql = "from PetInfo";

// 执行查询

Query query = session.createQuery(hql);

// 激活查询缓存

query.setCacheable(true);

// 使用自定义的查询缓存区域,若不设置,则使用标准查询缓存区域

query.setCacheRegion("myCacheRegion");

// 将查询结果赋给List对象

List<PetInfo> petList = query.list();

// 循环打印查询结果

for (int i=0;i<petList.size();i++)

{

// 循环得到PetInfo对象

PetInfo petInfo = petList.get(i);

System.out.println(petInfo.getPname());

}

// 关闭Session对象

session.close();

}

 

posted @ 2015-03-09 16:54  crazyYong  阅读(555)  评论(0编辑  收藏  举报