【问题标题】:Hibernate/Ehcache: evicting collections from 2nd level cache not synchronized with other DB readsHibernate/Ehcache:从 2 级缓存中逐出与其他数据库读取不同步的集合
【发布时间】:2009-10-01 19:22:35
【问题描述】:

我有一个使用 JPA、Hibernate 和 ehcache 以及 Spring 的声明式的应用程序 交易。 DB 上的负载相当高,因此所有内容都被缓存以加快速度, 包括收藏。现在集合单独缓存已经不是什么秘密了 从拥有它们的实体中,所以如果我删除一个作为此类元素的实体 缓存集合,持久化一个应该是一个元素的实体,或者更新一个 实体,使其从一个集合传播到另一个集合,我必须执行驱逐 手工。

所以我使用了一个休眠事件监听器来跟踪被插入、删除的实体 或更新并保存该信息以用于向 Spring 注册的事务同步 交易管理器采取行动。同步然后执行驱逐一次 事务已提交。

现在的问题是很多时候,其他一些并发事务设法找到 缓存中刚刚被驱逐的集合(这些事件通常是十分之一 根据日志分开第二个),自然会导致 EntityNotFoundException 发生。

如何正确同步这些东西?

我尝试在 TransactionSynchronization 的 4 种方法中的每一种中进行驱逐(其中 在相对于事务完成的不同时间点调用),它没有帮助。

【问题讨论】:

    标签: java hibernate collections transactions ehcache


    【解决方案1】:

    基本上,您需要做的是在集合正在处理或刚刚被驱逐的情况下强制从数据库读取。一种方法是在收到驱逐它的请求后但在进入事务以更改它之前将集合标记为脏。任何出现的并发事务都会检查脏标志,如果它设置为真,它应该从数据库中获取数据,否则它可以从缓存中读取。您可能需要更改数据库事务设置,以便并发事务阻塞,直到更新数据的事务完成,以便从数据库中读取正确的数据。事务完成后,您可以将脏标志重置为 false。

    只要驱逐持续,您还可以在更新、插入或删除到期时在缓存集合上创建锁。这将确保在驱逐过程完成之前没有其他事务可以读取/更改缓存的集合。

    【讨论】:

    • 顺便说一句,它在事务之外被逐出。我必须寻找 API 来将它们标记为脏,谢谢。另外,如何让 Hibernate 在您建议添加的锁上同步?
    • 显然,PersistentCollection 的脏标志是行不通的,因为不同的事务会得到同一个集合的不同实例。至于锁,我接下来会研究它,如果有人向我指出正确的 API,我将不胜感激。据我所知,EhCache 不支持锁定,看看第一件事。
    【解决方案2】:

    为什么您不能让集合保持最新状态?即当您添加一个对象时,将该对象添加到它所属的集合中。当你删除一个对象时,将它从它所在的集合中删除。根据我的经验,当使用带有 hibernate 或 jpa 的缓存时,对象的状态(而不是数据库的状态)被缓存,所以你需要确保你的对象模型内存中的对象模型与数据库中的对象模型同步。

    或者我错过了什么?为什么不能简单地保持集合更新?

    【讨论】:

    • 它是一个多线程应用程序,传递相同的最新实例和最新的集合似乎有点困难,因为有各种并发操作需要不同的时间来完成我倾向于使用 EntityManager.getById 来获取实体的最新状态。
    【解决方案3】:

    我认为您必须参考此链接:- Hibernate: Clean collection's 2nd level cache while cascade delete items 看,hibernate实际上并没有从缓存中删除对象..你可以从上面的链接中得到答案

    【讨论】:

      猜你喜欢
      • 2013-11-07
      • 1970-01-01
      • 2017-07-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多