我有一个使用 JPA、Hibernate 和 ehcache 的应用程序,以及 Spring 的声明式 交易。数据库上的负载相当高,因此所有内容都被缓存以加快速度, 包括 Collection 品。现在集合被单独缓存已经不是什么 secret 了 来自拥有它们的实体,所以如果我删除一个作为此类元素的实体 缓存集合,持久化一个应该是一个元素的实体,或者更新一个 实体使得它从一个集合移动到另一个集合,我必须执行驱逐 手工制作。
所以我使用了一个 hibernate 事件监听器,它跟踪实体被插入、删除 或更新并保存该信息以用于在 Spring 中注册的事务同步 事务管理器采取行动。一旦 事务已提交。
现在的问题是很多时候,一些其他并发事务设法找到 缓存中刚刚被逐出的集合(这些事件通常是十分之一 根据日志分开第二个),自然会导致 EntityNotFoundException 发生。
如何正确同步这些内容?
我尝试在 TransactionSynchronization 的 4 种方法中的每一种中进行驱逐( 在相对于事务完成的不同时间点被调用),它没有帮助。
最佳答案
本质上,您需要做的是在集合正在被逐出或刚刚被逐出的情况下强制从数据库中读取。一种方法是在收到驱逐请求后立即将集合标记为脏,但在进入事务以更改它之前。出现的任何并发事务都会检查脏标志,如果它设置为真,它应该从数据库中获取数据,否则它可以从缓存中读取。您可能需要更改数据库事务设置,以便并发事务阻塞直到更新数据的事务完成,以便从数据库中读取正确的数据。事务完成后,您可以将脏标志重置为 false。
您还可以在更新、插入或删除到期时在缓存集合上创建锁,只要驱逐持续。这将确保在驱逐过程完成之前,没有其他事务可以读取/更改缓存的集合。
关于java - hibernate/Ehcache : evicting collections from 2nd level cache not synchronized with other DB reads,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1505940/