Hibernate二级缓存(转)

这两天优化一个模块,那模块的问题是有时用户量访问量大时就慢了,于是想起去优化数据库操作,使用Hibernate的二级缓存。 
先是看了一些参考手册,然后找了几个配置的实例,测试成功。对二级缓存有了更多的认识。 
缓存本质上来说就是HashMap,一个ID对应一个Value,暂时放入内在或者硬盘,用的时候先从缓存里面取,若没有再去数据库取。避免缓存出现赃数据和缓存的命中率是一对死对头,若想命中效高,则存在的有效时间就得长,但这样却容易出现赃数据,因为更新的时间间隔长了。所以难点就在去找到一个平衡点,一个最优最能接受的点。 

Hibernate是对JDBC的轻型封装,要想做到像JDBC那样轻便、快捷,就需要比较优化的配置。Hibernate一级缓存是做在session层上的;而二级缓存则做在sessionFactory,所以session共享。 

下面先介绍下Hibernate的二级缓存(来自中文参考手册),然后介绍其配置。 

1、二级缓存(The Second Level Cache) 
Hibernate的Session在事务级别进行持久化数据的缓存操作。 当然,也有可能分别为每个类(或集合),配置集群、或JVM级别(SessionFactory级别)的缓存。 你甚至可以为之插入一个集群的缓存。注意,缓存永远不知道其他应用程序对持久化仓库(数据库)可能进行的修改 (即使可以将缓存数据设定为定期失效)。 

通过在hibernate.cache.provider_class属性中指定org.hibernate.cache.CacheProvider的某个实现的类名,你可以选择让Hibernate使用哪个缓存实现。Hibernate打包一些开源缓存实现,提供对它们的内置支持(见下表)。除此之外,你也可以实现你自己的实现,将它们插入到系统中。注意,在3.2版本之前,默认使用EhCache 作为缓存实现,但从3.2起就不再这样了。 

表 1.  缓存策略提供商(Cache Providers) 

Cache Provider class Type Cluster Safe Query Cache Supported
 
Hashtable (not intended for production use) org.hibernate.cache.HashtableCacheProvider memory    yes
 
EHCache org.hibernate.cache.EhCacheProvider memory, disk    yes
 
OSCache org.hibernate.cache.OSCacheProvider memory, disk    yes
 
SwarmCache org.hibernate.cache.SwarmCacheProvider clustered (ip multicast) yes (clustered invalidation)  
 
JBoss TreeCache org.hibernate.cache.TreeCacheProvider clustered (ip multicast), transactional yes (replication) yes (clock sync req.)




2、缓存映射(Cache mappings) 
类或者集合映射的“<cache>元素”可以有下列形式: 

Java代码 
  1. <cache   
  2.     usage="transactional|read-write|nonstrict-read-write|read-only"  
  3.     region="RegionName"  
  4.     include="all|non-lazy"  
  5. />  

usage(必须)说明了缓存的策略: transactional、 read-write、 nonstrict-read-write或 read-only。 

region (可选, 默认为类或者集合的名字(class or collection role name)) 指定第二级缓存的区域名(name of the second level cache region) 

include (可选,默认为 all) non-lazy 当属性级延迟抓取打开时, 标记为lazy="true"的实体的属性可能无法被缓存 


另外(首选?), 你可以在hibernate.cfg.xml中指定<class-cache>和 <collection-cache> 元素。 

这里的usage 属性指明了缓存并发策略(cache concurrency strategy)。 

3、策略:只读缓存(Strategy: read only) 
如果你的应用程序只需读取一个持久化类的实例,而无需对其修改, 那么就可以对其进行只读 缓存。这是最简单,也是实用性最好的方法。甚至在集群中,它也能完美地运作。 

Java代码 
  1. <class name="eg.Immutable" mutable="false">  
  2.     <cache usage="read-only"/>  
  3.     ....  
  4. </class>  

19.2.3.  策略:读/写缓存(Strategy: read/write) 
如果应用程序需要更新数据,那么使用读/写缓存 比较合适。 如果应用程序要求“序列化事务”的隔离级别(serializable transaction isolation level),那么就决不能使用这种缓存策略。 如果在JTA环境中使用缓存,你必须指定hibernate.transaction.manager_lookup_class属性的值, 通过它,Hibernate才能知道该应用程序中JTA的TransactionManager的具体策略。 在其它环境中,你必须保证在Session.close()、或Session.disconnect()调用前, 整个事务已经结束。 如果你想在集群环境中使用此策略,你必须保证底层的缓存实现支持锁定(locking)。Hibernate内置的缓存策略并不支持锁定功能。 

Java代码 
  1. <class name="eg.Cat" .... >  
  2.     <cache usage="read-write"/>  
  3.     ....  
  4.     <set name="kittens" ... >  
  5.         <cache usage="read-write"/>  
  6.         ....  
  7.     </set>  
  8. </class>  

4、策略:非严格读/写缓存(Strategy: nonstrict read/write) 
如果应用程序只偶尔需要更新数据(也就是说,两个事务同时更新同一记录的情况很不常见),也不需要十分严格的事务隔离, 那么比较适合使用非严格读/写缓存策略。如果在JTA环境中使用该策略, 你必须为其指定hibernate.transaction.manager_lookup_class属性的值, 在其它环境中,你必须保证在Session.close()、或Session.disconnect()调用前, 整个事务已经结束。 

5、 策略:事务缓存(transactional) 
Hibernate的事务缓存策略提供了全事务的缓存支持, 例如对JBoss TreeCache的支持。这样的缓存只能用于JTA环境中,你必须指定 为其hibernate.transaction.manager_lookup_class属性。 

没有一种缓存提供商能够支持上列的所有缓存并发策略。下表中列出了各种提供器、及其各自适用的并发策略。 

表 2.  各种缓存提供商对缓存并发策略的支持情况(Cache Concurrency Strategy Support) 

Cache read-only nonstrict-read-write read-write transactional
 
Hashtable (not intended for production use) yes yes yes  
 
EHCache yes yes yes   
 
OSCache yes yes yes  
 
SwarmCache yes yes    
 
JBoss TreeCache yes     yes





二级缓存配置:    
   
1、首先要打开二级缓存,在hibernate.cfg.xml中添加如下配置:    
<property name="hibernate.cache.use_second_level_cache">true</property>   
   
2、Hibernate的二级缓存使用第三方的缓存工具来实现,所以我们需要指定Hibernate使用哪个缓存工具。如下配置指定Hibernate使用EhCache缓存工具。    
<property name="hibernate.cache.provider_class">org.hibernate.cache.EhCacheProvider</property>   
   
3、Hibernate在默认情况下并不会对所有实体对象进行缓存,所以,我们需要指定缓存哪些对象,在实体对象的映射文件中(相应的<class>标签内部),添加如下配置:    
<cache usage="read-only"/>   
   
usage="read-only"是“只读”缓存策略。    
   
注意,这个<cache>标签只能放在<class>标签的内部,而且必须处在<id>标签的前面!!!这个<cache>标签放在哪些<class>标签下面,就说明会多这些类的对象进行缓存 
(缓存策略既可放到hibernate.cfg.xml中,也可放到对应实体的映射文件中)    
   
4、对于第3步,有一个可选的方案是在hibernate.cfg.xml文件中指定哪些类的对象需要缓存,而不需要使用<cache>标签来指定。如:   
   在hibernate.cfg.xml中添加如下配置:    
   <class-cache class="com.bjsxt.hibernate.Classes" usage="read-only" />   
      
   注意,这个<class-cache>标签必须放在<mapping>标签的后面!!   

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

Java代码 
  1. <?xml version="1.0" encoding="UTF-8"?>   
  2. <ehcache>   
  3.  <diskStore path="java.io.tmpdir"/>   
  4.   <defaultCache   
  5.    maxElementsInMemory="10000" <!-- 缓存最大数目 -->   
  6.    eternal="false" <!-- 缓存是否持久 -->   
  7.    overflowToDisk="true" <!-- 是否保存到磁盘,当系统当机时-->   
  8.    timeToIdleSeconds="300" <!-- 当缓存闲置n秒后销毁 -->   
  9.    timeToLiveSeconds="180" <!-- 当缓存存活n秒后销毁-->   
  10.    diskPersistent="false"   
  11.    diskExpiryThreadIntervalSeconds= "120"/>   
  12. </ehcache>   


  2、在Hibernate配置文件中设置: 

Java代码 
  1. <!-- 设置Hibernate的缓存接口类,这个类在Hibernate包中 -->   
  2. <property name="cache.provider_class">org.hibernate.cache.EhCacheProvider</property>   
  3.  <!-- 是否使用查询缓存 -->   
  4.  <property name="hibernate.cache.use_query_cache"true</property>   
  5.   如果使用spring调用Hibernate的sessionFactory的话,这样设置:   
  6.   <!--HibernateSession工厂管理 -->   
  7.    <bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">   
  8.    <property name="dataSource">   
  9.     <ref bean="datasource" />   
  10.    </property>   
  11.    <property name="hibernateProperties">   
  12.    <props>   
  13.     <prop key="hibernate.dialect">org.hibernate.dialect.Oracle9Dialect</prop>   
  14.     <prop key="connection.provider_class">org.hibernate.connection.C3P0ConnectionProvider</prop>   
  15.     <prop key="hibernate.show_sql"true</prop>   
  16.     <prop key="hibernate.cache.use_query_cache"true</prop>   
  17.     <prop key="hibernate.cache.provider_class">org.hibernate.cache.EhCacheProvider</prop>   
  18.    </props>   
  19.  </property>   
  20.  <property name="mappingDirectoryLocations">   
  21.   <list>   
  22.    <value>/WEB-INF/classes/cn/rmic/manager/hibernate/</value>   
  23.   </list>   
  24.  </property>   
  25. </bean>   

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

  3、在Hbm文件中添加<cache usage="read-only"/> 

  4、如果需要“查询缓存”,还需要在使用Query或Criteria()时设置其setCacheable(true);属性 

  5、只有自己动手才知道,自己写一段简单的测试程序(两次查询),如果成功的话第二次查询时不会读取数据库(设置成让Hibernate显示sql语句,方便看结果)

猜你喜欢

转载自automaticthoughts.iteye.com/blog/1673413