我正在使用 java 1.6、spring 2.5、hibernate 3.3.1 和 ehcache 2.6.0。程序连接到两个数据库。有两种 ehcache 配置,但在本例中只使用一种。 在批处理结束时,程序返回此错误:
2012-10-23 15:44:43,406 ERROR (AbstractReadWriteEhcacheAccessStrategy.java:159) - Cache dao.data.MyObject Key dao.data.MyObject#28 Lockable : null
A soft-locked cache entry was removed already. Out of balance lock/unlock sequences ?
什么会产生这个错误?
最佳答案
我现在正受此困扰,所以我将分享我的发现。
首先,一些背景:
- 我们使用 Hibernate 3.5.2 和 EhCache 2.7.0
- 只有一个数据库(另一个只读访问,但没有使用缓存,因为它是在外部更新的),单个缓存实例(无集群)
- 问题发生在更新与 InheritanceType.JOINED 和 CacheConcurrencyStrategy.READ_WRITE 映射的实体时(但不是当我们切换到 NONSTRICT_READ_WRITE 时)。此外,从代码检查来看,删除时也会发生这种情况。
我通过调试 Hibernate 和 EhCache 代码发现了什么:
- Hibernate 的 EntityUpdateAction(在 execute() 中)调用 EntityRegionAccessStrategy.lockItem()
- EhCache 的实现(在 AbstractReadWriteEhcacheAccessStrategy 中)将给定键的映射从缓存实体更改为锁
- Hibernate 检测到实体映射到超过 1 个表,因此需要缓存失效(参见 AbstractEntityPersister.isCacheInvalidationRequired())
- 它继续调用 persister.getCacheAccessStrategy().remove(),在 EhCache 的实现中,它会删除给定缓存键的映射。然而,虽然 Hibernate 期望这实际上会删除缓存的实体,但使用 EhCache 它会删除锁(在第 2 步中放在那里。)
- 事务完成后,在 EntityUpdateAction.doAfterTransactionCompletion() 中,Hibernate 检测到需要使缓存失效,然后继续调用 unlockItem(),如果没有给定缓存键的映射,则调用失败,导致您描述的错误消息<
在我看来,这是 lockItem() 和 unlockItem()(在 READ_WRITE 情况下)的 EhCache 实现中的一个问题。它不应该用锁代替实际元素,而是单独存放锁。至少,在这种情况下,可以说 Hibernate 和 EhCache 不是 100% 兼容的。
最后几点说明:
- 看来这个错误是无害的,可以通过 log4j 配置安全地抑制。
- 我已经设法在不同的场景中重复此操作(归结为相同的锁定/删除/解锁顺序)。这一次,不是加入继承,而是 native SQL 触发了删除。其他一切都几乎相同。
- Hibernate 和 EhCache 代码的相关位:EntityRegionAccessStrategy、EntityAction、CollectionRegionAccessStrategy、CollectionAction 和相关的实现/扩展具体类。
HTH
关于java - 已删除软锁定缓存条目。失衡的锁定/解锁序列?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13032552/