2012-04-18 18 views
3

我是java/spring/hibernate中的新成员,经过几年的.Net编程后,在java中真正感受到了爱。Hibernate不会驱逐查询缓存(不可重复读取问题)

现在我正在使用Spring(MVC,声明性事务)和Hibernate(3.6,作为缓存provier-ehCache 2.5)的web应用程序。我有一些只读和读写enitties,我想用Hibernate缓存和查询缓存来缓存。

当我为只读实体使用缓存时,一切正常。我添加了读写实体并使用jMeter运行性能测试。对于读写实体,我面临着不可重复读取的问题。例如。有几个并发线程正在读写实体表。

线3的查找值:

16:34:45,304 DEBUG [http-bio-8080-exec-3] cache.StandardQueryCache:  (StandardQueryCache.java:136) - cached query results were not up to date 
16:34:45,304 DEBUG [http-bio-8080-exec-3] hibernate.SQL:(SQLStatementLogger.java:111) - select virtualdev0_.virtual_device_class_id as virtual1_45_,  virtualdev0_.virtual_device_class as virtual2_45_, virtualdev0_.sitebox_id as sitebox3_45_, virtualdev0_.timestamp as timestamp45_ from virtual_device_class virtualdev0_ where  virtualdev0_.sitebox_id=? 

它发现缓存不是最新的,并且负载实体,并将它们添加到第二级缓存,从这里物化和回报......连续的过程和多达16个:34:45826

同时螺纹9删除实体之一,并更新二级缓存+时间戳:

16:34:45,799 DEBUG [http-bio-8080-exec-9] hibernate.SQL:(SQLStatementLogger.java:111) - delete from virtual_device_class where virtual_device_class_id=? 
16:34:45,814 DEBUG [http-bio-8080-exec-9] cache.UpdateTimestampsCache:(UpdateTimestampsCache.java:95) - Invalidating space [virtual_device_class], timestamp: 5466792287494145 

线程3继续看家活动最后增加了查询结果的查询缓存(请注意,时间戳会比timpestamp螺纹9的删除操作更高):

16:34:45,826 DEBUG [http-bio-8080-exec-3] cache.StandardQueryCache:(StandardQueryCache.java:96) - caching query results in region: org.hibernate.cache.StandardQueryCache; timestamp=5466792287543296 

因此,在这个时间点删除ID将在查询缓存和查询缓存将被认为是最新的。

16:34:45,852 DEBUG [http-bio-8080-exec-9] cache.UpdateTimestampsCache:(UpdateTimestampsCache.java:122) - [virtual_device_class] last update timestamp: 5466792287494145, result set timestamp: 5466792287543296 

所以,当你试图让查找再次它将在查询缓存,然后将开始从第二高速缓存物化实体。

16:34:45,852 DEBUG [http-bio-8080-exec-9] cache.StandardQueryCache:(StandardQueryCache.java:140) - returning cached query results 

但删除的项目不会在那里,所以查询分贝将完成。

16:34:45,863 DEBUG [http-bio-8080-exec-9] loader.Loader:(Loader.java:2022) - loading entity: [com.test.models.VirtualDeviceClass#0b2f363f-fbb9-4d17-8f86-af86ebb5100c] 
16:34:45,873 DEBUG [http-bio-8080-exec-9] hibernate.SQL:(SQLStatementLogger.java:111) - select virtualdev0_.virtual_device_class_id as virtual1_45_0_, virtualdev0_.virtual_device_class as virtual2_45_0_, virtualdev0_.sitebox_id as sitebox3_45_0_, virtualdev0 

由于我使用Load方法,因此抛出异常,如果实体没有在数据库中找到。 在我的情况下,实体很少更新它可能发生,这令我担心。我有几个想法如何尝试克服这个问题:

a)将trx隔离级别设置为DB中的可重复读取(但不要认为这会有所帮助,因为在从db读取数据之后添加到缓存逻辑) b)手动强制标准查询缓存驱逐在实体删除/更新 C)根本不使用查询缓存(尝试路由大多数数据库查询使用第二缓存)

有没有人面对这个问题之前, ?

回答

1

我已经迁移到Hibernate 4,它现在工作正常。

这个问题可能已经涉及到同步块方法SessionFactory.getQueryCache(String regionName)

link to hibernate issue

被删除