现在的位置: 首页 > 综合 > 正文

Hibernate二级缓存配置详解

2019年03月08日 ⁄ 综合 ⁄ 共 2888字 ⁄ 字号 评论关闭
使用二级缓存的前置条件 
Hibernate <wbr>二级缓存配置详解Hibernate <wbr>二级缓存配置详解Hibernate <wbr>二级缓存配置详解Hibernate <wbr>二级缓存配置详解
你的hibernate程序对数据库有独占的写访问权,其他的进程更新了数据库,hibernate是不可能知道的。你操作数据库必需直接通过hibernate,如果你调用存储过程,或者自己使用jdbc更新数据库,hibernate也是不知道的。hibernate3.0的大批量更新和删除是不更新二级缓存的,但是据说3.1已经解决了这个问题。 
这个限制相当的棘手,有时候hibernate做批量更新、删除很慢,但是你却不能自己写jdbc来优化,很郁闷吧。 
SessionFactory也提供了移除缓存的方法,你一定要自己写一些JDBC的话,可以调用这些方法移除缓存,这些方法是: 

void evict(Class persistentClass) 
         Evict all entries from thesecond-level cache. 
void evict(Class persistentClass, Serializableid) 
         Evict an entry from thesecond-level cache. 
void evictCollection(String roleName) 
         Evict all entries from thesecond-level cache. 
void evictCollection(String roleName, Serializableid) 
         Evict an entry from thesecond-level cache. 
void evictQueries() 
         Evict any query result setscached in the default query cache region. 
void evictQueries(String cacheRegion) 
         Evict any query result setscached in the named query cache region. 
不过我不建议这样做,因为这样很难维护。比如你现在用JDBC批量更新了某个表,有3个查询缓存会用到这个表,用evictQueries(StringcacheRegion)移除了3个查询缓存,然后用evict(ClasspersistentClass)移除了class缓存,看上去好像完整了。不过哪天你添加了一个相关查询缓存,可能会忘记更新这里的移除代码。如果你的jdbc代码到处都是,在你添加一个查询缓存的时候,还知道其他什么地方也要做相应的改动吗? 
 1.在Web项目src目录下的hibernate.cfg.xml添加配置项:
<!-- 开启二级缓存 默认开启 -->
<propertyname="cache.use_second_level_cache">true</property>
<!-- 指定二级缓存的拥有者 -->
<propertyname="cache.provider_class">
net.sf.ehcache.hibernate.EhCacheProvider
</property>
<!-- 指定二级缓存的实体类  可在实体配置文件中进行配置
<class-cache usage="read-only"class="com.lovesmile.oa.entity.User"/>
-->
<propertyname="cache.use_query_cache">true</property>
<propertyname="generate_statistics">true</property>
2.在Web项目src目录下添加ehcache.xml,它包含如下内容:
ehcache.xml
   
 
   
       maxElementsInMemory="10000"
       eternal="false"
       overflowToDisk="true"
       timeToIdleSeconds="120"
       timeToLiveSeconds="120"
       diskPersistent="false"
      diskExpiryThreadIntervalSeconds="120"/>
   
       maxElementsInMemory="10000"
       eternal="false"
       timeToIdleSeconds="300000"
       timeToLiveSeconds="600000"
       overflowToDisk="true"/>
       
3.第一种:在实体xml映射中添加(位置如下:)
    <classname="com.lovesmile.oa.entity.Department" table="DEPARTMENTS"schema="LOVESMILE">
    <cacheusage="read-write"/><!-- 缓存策略-->
       <id name="id"type="java.lang.Integer">
          <column name="ID"/>
          <generator class="sequence">
          <paramname="sequence">SEQ_USER</param>
          </generator>
       </id>
3.第二种:注解方式:或者在实体类添加(位置:在类上添加)
@Entity
@Table(name = "DEPARTMENTS", schema = "LOVESMILE")
@Cache(usage=CacheConcurrencyStrategy.READ_WRITE)
public class Department implements java.io.Serializable{...
注意点:
1.使用hql查询语句时:hql将作为key值存在二级缓存集合中,如果缓存存在相同key,将不进行数据库查询。
2.创建query,调用query.setCacheable(true)--->(开启二级缓存,默认为关闭的);进行缓存,每个需要用到二级缓存的query都要调用。
3....
---------------------------------------------------- 
总结: 
不要想当然的以为缓存一定能提高性能,仅仅在你能够驾驭它并且条件合适的情况下才是这样的。hibernate的二级缓存限制还是比较多的,不方便用jdbc可能会大大的降低更新性能。在不了解原理的情况下乱用,可能会有1+N的问题。不当的使用还可能导致读出脏数据。 
如果受不了hibernate的诸多限制,那么还是自己在应用程序的层面上做缓存吧。 
在越高的层面上做缓存,效果就会越好。就好像尽管磁盘有缓存,数据库还是要实现自己的缓存,尽管数据库有缓存,咱们的应用程序还是要做缓存。因为底层的缓存它并不知道高层要用这些数据干什么,只能做的比较通用,而高层可以有针对性的实现缓存,所以在更高的级别上做缓存,效果也要好些吧。
然后就是自己测试了 ...

抱歉!评论已关闭.