【问题标题】:Why does hibernate/ehcache second level cache always miss within the same session?为什么 hibernate/ehcache 二级缓存总是在同一个会话中丢失?
【发布时间】:2011-06-10 11:47:43
【问题描述】:

我有一个长期运行的 EntityManager,我会定期 clear()。我在我的一个实体上配置了读写缓存。

我进行了一些调查,我可以看到该实体存在于缓存中。我什至可以看到来自net.sf.ehcache.Cache.searchInStoreWithStats() 的缓存命中。但是,如果实体的时间戳晚于创建会话时的时间戳,ehcache 将不会返回该实体:参见AbstractReadWriteEhcacheAccessStrategy.get(Object, long)。

这种行为的原因是什么?有没有一种方法可以自定义 hibernate 或 ehcache 以在单个 EntityManager 中实现缓存命中?

【问题讨论】:

  • 抱歉指出显而易见的问题,但是您是否覆盖了等号和哈希码?如果你这样做了,你确定它们是正确的吗?
  • 在实体上?是的,我有。不过,我不确定这是否重要,因为 Hibernate 不会将实体本身存储在二级缓存中。

标签: java hibernate ehcache


【解决方案1】:

看起来这是读写缓存的一个属性:您无法从同一会话中创建的缓存中获取实体。

非严格的读写缓存不比较时间戳,所以这确实会在第一次 load() 之后实现缓存命中。

更好的是,事务缓存在persist() 之后填充缓存,因此第一个load() 将导致缓存命中。由于我与数据库的交互完全在单个 JVM 中的单个线程中进行,因此我相信这是可以安全使用的。

【讨论】:

  • 那是有道理的。如果是同一个会话,也许 hibernate 期望在一级缓存中找到它,或者它正在等待刷新以查看实体是否有效
【解决方案2】:

正如 JavaDoc 所说:时间戳表示实体是在事务开始后创建的,因此事务不可能看到它(根据 ACID)。

所以看起来你有几个事务,比如 A 和 B。你启动 B,然后是 A,然后 A 创建实例 X,然后 B 尝试查找 X -> 缓存未命中,因为 A 尚未提交,但(例如)。

【讨论】:

  • 实体是在创建会话之后创建的,但它是在之前的事务中创建的。而且我的应用程序没有任何并发​​事务。
  • EHCache 的想法不同,所以很可能你错了。我建议添加记录事务创建/提交以确保满足您的期望。
  • 我已经完成了日志记录和调试。当我为每个persist() 和getReference() 操作创建新会话时,我会遇到缓存命中,但是当我在一个会话中坚持、提交、clear() 和getReference() 时,我会遇到缓存未命中。
猜你喜欢
  • 1970-01-01
  • 2010-11-20
  • 2012-12-12
  • 2014-11-10
  • 1970-01-01
  • 1970-01-01
  • 2010-10-28
  • 1970-01-01
  • 2010-09-25
相关资源
最近更新 更多