1

我们正在尝试让缓存在我们的应用程序中工作,并且很难让它真正工作。我们没有非常复杂的配置,至少对于应用程序的这一部分来说,所以这真的很令人沮丧,我最终不得不投身于 StackOverflow 社区的温柔怜悯中。

首先,目前,我们停留在 Spring 3.0 和 Hibernate 3.6,因此使用新的 Spring 3.1 @Cacheable 注释和所有其他东西对我们来说不是一个选择。

我已将堆栈的版本放在主题中,我们拥有的是该堆栈的非常典型的配置:

  • 我们的 Hibernate 实体只用@Entity 定义,DAO 用@Repository 定义,服务用@Service 定义
  • 事务边界由@Transactional 设置
  • 我通过将 ehcache-core 添加到 pom.xml 并将以下属性添加到 Hibernate 属性映射中来添加缓存:
<prop key="hibernate.cache.use_second_level_cache">true</prop>
<prop key="hibernate.cache.use_query_cache">true</prop>
<prop key="hibernate.cache.region.factory_class">net.sf.ehcache.hibernate.SingletonEhCacheRegionFactory</prop>

然后我将@Cache注释添加到我的实体类中,如下所示:

@Entity
@Cache(usage = CacheConcurrencyStrategy.READ_WRITE, region = "config")
public class Configuration extends AbstractHibernateEntity implements Serializable {

老实说,我以为我已经完成了。是的,我如此轻松地配置缓存!你可以看到它在工作,当缓存上线时,日志中有很多消息。那太棒了!

只是事实证明,缓存已经上线,没有任何东西被缓存。我现在已经对此进行了两天的研究,但不知道为什么我的对象没有被缓存。我已经尝试添加<cache name="..."/>到我的ehcache.xml中,在我的@Cache注释上指定区域,检查缓存统计信息等。我已经为net.sf.ehcacheorg.hibernate.cache包添加了调试日志记录。我根本看不出是什么阻止了将对象保存到缓存并在那里访问它们。

在我们意识到我们的 Web 应用程序没有缓存之后,我回到依赖库并意识到它们也没有缓存(我在单元测试中添加了缓存以确保缓存不会破坏单元测试;它没有't 但也许这只是因为它没有缓存)。所以我一直在研究我们的一个较低级别的依赖项,想知道我是否可以弄清楚如何让它在那个级别工作,我可以把它拉到网络应用程序级别。这是一个很棒的理论,只是我什至不能让它在较低的层次上工作!

在我的日志中,我收到了很多消息。下面是net.sf.ehcache的调试输出示例:

14:03:20,795  INFO                           net.sf.ehcache: 284 - CACHE HITS:  0
14:03:20,796  INFO                           net.sf.ehcache: 284 - IN-MEM HITS: 0
14:03:20,796  INFO                           net.sf.ehcache: 284 - CACHE MISS:  0
14:03:20,796  INFO                           net.sf.ehcache: 284 - IN-MEM MISS: 0
14:03:20,796  INFO                           net.sf.ehcache: 284 - EVICTIONS:   0
14:03:20,797  INFO                           net.sf.ehcache: 284 - MEM OBJ CT:  0
14:03:20,886 DEBUG bernate.regions.EhcacheGeneralDataRegion: 211 - key: xhbm_configuration_data value: 5643835231789056
14:03:20,890 DEBUG bernate.regions.EhcacheGeneralDataRegion: 211 - key: xhbm_configuration value: 5643835231805440
14:03:20,891 DEBUG bernate.regions.EhcacheGeneralDataRegion: 211 - key: xhbm_configuration_data value: 5643834986045441
14:03:20,891 DEBUG bernate.regions.EhcacheGeneralDataRegion: 211 - key: xhbm_configuration value: 5643834986045441
14:03:20,897 DEBUG bernate.regions.EhcacheGeneralDataRegion: 211 - key: xhbm_configuration_data value: 5643835231834112
14:03:20,898 DEBUG bernate.regions.EhcacheGeneralDataRegion: 211 - key: xhbm_configuration value: 5643835231838208
14:03:20,898 DEBUG bernate.regions.EhcacheGeneralDataRegion: 211 - key: xhbm_configuration_data value: 5643834986078209
14:03:20,899 DEBUG bernate.regions.EhcacheGeneralDataRegion: 211 - key: xhbm_configuration value: 5643834986078209

org.hibernate.cache日志中,我得到很多这样的东西:

14:47:26,077 DEBUG rg.hibernate.cache.UpdateTimestampsCache: 168 - Pre-invalidating space [xhbm_configuration_data]
14:47:26,081 DEBUG rg.hibernate.cache.UpdateTimestampsCache: 168 - Pre-invalidating space [xhbm_configuration]
14:47:26,082 DEBUG rg.hibernate.cache.UpdateTimestampsCache: 168 - Invalidating space [xhbm_configuration_data], timestamp: 5643845820751872
14:47:26,082 DEBUG rg.hibernate.cache.UpdateTimestampsCache: 168 - Invalidating space [xhbm_configuration], timestamp: 5643845820751872
14:47:26,089 DEBUG rg.hibernate.cache.UpdateTimestampsCache: 168 - Pre-invalidating space [xhbm_configuration_data]
14:47:26,091 DEBUG rg.hibernate.cache.UpdateTimestampsCache: 168 - Pre-invalidating space [xhbm_configuration]
14:47:26,092 DEBUG rg.hibernate.cache.UpdateTimestampsCache: 168 - Invalidating space [xhbm_configuration_data], timestamp: 5643845820792832
14:47:26,092 DEBUG rg.hibernate.cache.UpdateTimestampsCache: 168 - Invalidating space [xhbm_configuration], timestamp: 5643845820792832
14:47:26,125 DEBUG rg.hibernate.cache.UpdateTimestampsCache: 168 - Pre-invalidating space [xhbm_configuration_data]
14:47:26,130 DEBUG rg.hibernate.cache.UpdateTimestampsCache: 168 - Pre-invalidating space [xhbm_configuration]
14:47:26,131 DEBUG rg.hibernate.cache.UpdateTimestampsCache: 168 - Invalidating space [xhbm_configuration_data], timestamp: 5643845820952576
14:47:26,132 DEBUG rg.hibernate.cache.UpdateTimestampsCache: 168 - Invalidating space [xhbm_configuration], timestamp: 5643845820952576

从这里我真的不知道还能说什么。完整代码可从我的 Bitbucket 存储库(它是 Mercurial,而不是 git)在https://bitbucket.org/rherrick/nrg_config或从 Dropbox 的 zip 获得https://dl.dropboxusercontent.com/u/42711610/ nrg_config.zip。您应该能够从 Maven 运行单元测试:

mvn clean install

如果有人能帮我弄清楚这里到底出了什么问题,我会欣喜若狂!你不想让我欣喜若狂吗?我知道我知道:)

说真的,提前非常感谢,之后将非常感谢您对这个问题的任何帮助。

4

2 回答 2

1

据我了解,对象的二级缓存仅在您调用load getlist时才会使用Session。我在你的代码中看不到这样的调用。

setCacheable只有在调用QueryCriteria对象时才会使用查询缓存。再一次,您永远不会在代码中调用该方法。

于 2013-09-04T19:49:11.417 回答
0

亚历山大,

您走在正确的轨道上,但这只是导致问题的少数因素之一。实际上有三个因素在发生:

  1. 我们的代码实际上是调用 load()、get()、list() 等,但它大部分都包含在我们的框架代码中。我浏览并模板化了一堆代码以显式强制缓存在那里。这开始了一些缓存。
  2. JPA/Hibernate 实体不应该初始化任何东西!我们有一个基类,它在实例化时设置了几个标志和时间戳。当检索到一个对象时,这最终使该对象看起来很脏,需要完全用完数据库。这对我们的框架来说确实是一个大问题。
  3. 设置瞬态属性时注意事务边界。当您进入然后退出标记为 @Transactional 的方法时,对对象的任何更改都将被保留,无论您是否在该对象上调用了 session.save(),如此处所述。这导致对象不断无法与缓存版本匹配(尽管我曾认为对象的修改版本会匹配缓存,但这似乎没有发生)。

最后,这最终很难诊断,主要是因为它不是一个单一的因素,而是由许多不同的事情共同造成的!

于 2013-09-05T20:08:10.987 回答