在Spring、Hibernate中使用Ehcache缓存

来源:互联网 发布:sql删除部分字段 编辑:程序博客网 时间:2024/06/01 03:57
在Spring、Hibernate中使用Ehcache缓存

EhCache是Hibernate的二级缓存技术之一,可以把查询出来的数据存储在内存或者磁盘,节省下次同样查询语句再次查询数据库,大幅减轻数据库压力;

EhCache的使用注意点


当用Hibernate的方式修改表数据(save,update,delete等等),这时EhCache会自动把缓存中关于此表的所有缓存全部删除掉(这样能达到同步)。但对于数据经常修改的表来说,可能就失去缓存的意义了(不能减轻数据库压力);


在比较少更新表数据的情况下,EhCache一般要使用在比较少执行write操作的表(包括update,insert,delete等)[Hibernate的二级缓存也都是这样];对并发要求不是很严格的情况下,两台机子中的缓存是不能实时同步的;

1、首先要在hibernate.cfg.xml配置文件中添加配置,在hibernate.cfg.xml中的mapping标签上面加以下内容:

<!-- 开启二级缓存 -->
<property name="hibernate.cache.use_second_level_cache">true</property>


<!-- 缓存类型程序 -->
<property name="hibernate.cache.provider_class">org.hibernate.cache.EhCacheProvider</property>

如果你是整合在spring配置文件中,那么你得配置你的applicationContext.xml中相关SessionFactory的配置


<prop key="hibernate.cache.use_second_level_cache">true</prop><prop key="hibernate.cache.provider_class">org.hibernate.cache.EhCacheProvider</prop>


2、在hibernate.cfg.xml配置文件中加入使用缓存的属性
<!-- class-cache config -->  <class-cache class="com.hoo.hibernate.entity.User" usage="read-write" /> 

当然你也可以在User.hbm.xml映射文件需要Cache的配置class节点下,加入类似如下格式信息:
<cache usage="transactional|read-write|nonstrict-read-write|read-only" />

注意:cache节点元素应紧跟class元素


关于选择缓存策略依据:


ehcache不支持transactional,其他三种可以支持。

read- only:无需修改, 可以对其进行只读缓存,注意:在此策略下,如果直接修改数据库,即使能够看到前台显示效果,但是将对象修改至cache中会报error,cache不会发生作用。另:删除记录会报错,因为不能在read-only模式的对象从cache中删除。


read-write:需要更新数据,那么使用读/写缓存比较合适,前提:数据库不可以为serializable transaction isolation level(序列化事务隔离级别)


nonstrict-read-write:只偶尔需要更新数据(也就是说,两个事务同时更新同一记录的情况很不常见),也不需要十分严格的事务隔离,那么比较适合使用非严格读/写缓存策略。

3、ehcache.xml的配置:

将ehcache.xml文件拷贝到src目录下,其中<diskStore/>为缓存文件存放路径。
<pre name="code" class="plain"><ehcache>    <diskStore path="f:cache"/>    <defaultCache        maxElementsInMemory="10000"        eternal="false"        timeToIdleSeconds="120"        timeToLiveSeconds="120"        overflowToDisk="true"        /></ehcache>


特别说明:

如果需要加入查询缓存则加入以下代码:


<!-- 开启查询缓存 -->
<property name="hibernate.cache.use_query_cache">true</property>

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


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


建 议
1、建议不要使用sql直接执行数据持久化对象的数据的更新,但是可以执行 批量删除。(系统中需要批量更新的地方也较少)

2、如果必须使用sql执行数据的更新,必须清空此对象的缓存数据。调用
SessionFactory.evict(class)SessionFactory.evict(class,id)
等方法。


3、在批量删除数据量不大的时候可以直接采用hibernate的批量删除,这样就不存在绕开hibernate执行sql产生的缓存数据一致性的问题。


4、不推荐采用hibernate的批量删除方法来删除大批量的记录数据。


原因是hibernate的批量删除会执行1条查询语句外加 满足条件的n条删除语句。而不是一次执行一条条件删除语句!!


当待删除的数据很多时会有很大的性能瓶颈!!!如果批量删除数据量较大,比如超过50条,可以采用JDBC直接删除。这样作的好处是只执行一条sql删除语句,性能会有很大的改善。同时,缓存数据同步的问题,可以采用 hibernate清除二级缓存中的相关数据的方法。


调用 SessionFactory.evict(class) ;SessionFactory.evict(class,id)等方法。

所以说,对于一般的应用系统开发而言(不涉及到集群,分布式数据同步问题等),因为只在中间关联表执行批量删除时调用了sql执行,同时中间关联表一般是执行条件查询不太可能执行按id查询。所以,此时可以直接执行sql删除,甚至不需要调用缓存的清除方法。这样做不会导致以后配置了二级缓存引起数据有效性的问题。

退一步说,即使以后真的调用了按id查询中间表对象的方法,也可以通过调用清除缓存的方法来解决。


0 0
原创粉丝点击