1

我们正在使用 Hibernate 运行 JBoss,并且遇到了这个问题。

当会话 bean 使用 EntityManager 查找实体时,它可能已经存在于 EntityManager 的缓存中,并且它的状态可能已经过时。如果代码使用这样的实体来做出决定,它可能会做出错误的决定,从而产生错误。

这是一个示例案例。

HTTP 请求 1. 会话 bean 创建一个实体实例并将其存储,并将字段“A”设置为值 1。持久化实体的 ID = 4。

HTTP 请求 2。会话 bean 查找 ID = 4 的实体,将其字段“A”设置为值 2 并保存它。

HTTP 请求 3。会话 bean 查找 ID = 4 的实体并检查它的字段“A”。如果值为 1 则做一件事,如果值为 2 则做另一件事。

如果请求 3 中的 EM 恰好与请求 1 中的 EM 相同,则会发生不希望的行为。我已经对此进行了测试并得到了大约。10%的失败案例。

所以问题是 - 如何避免这种情况?每次我必须确保实体是最新的时调用 em.refresh() 或 em.clear() 似乎是在浪费资源。

4

1 回答 1

1

阿尔乔姆,

这似乎是您的问题中反复出现的 主题:-)

虽然我知道您之前得到的答案(包括我的)可能不是您所希望的,但它们不会改变:

  • Entity Manager 是一个映射到 Hibernate 的会话,通常需要是短暂的。是与 Hibernate 会话有关的工作单元、事务和范围的一个很好的解释,如果您以前没有看过它,请看一下。
  • 如果您的应用程序始终坚持使用实体管理器,您需要认真考虑更改该策略;如果你只是在几个你确实需要比使用refresh()方法进行长时间交易的地方这样做,那么肯定是万恶之源。
  • 与具有集群实现的二级缓存不同,会话级缓存在设计上不会在不同会话(实体管理器)之间同步,并且通过 Hibernate 提供的乐观锁定或应用程序级锁定来处理对同一实体的并发更新。
  • 理论上,您可以(前提是您的 ORM 访问分离得足够好)维护自己的缓存(如果需要,可集群)各种实体管理器持有的实体;您需要为每个事件注册适当的事件侦听器以保持缓存同步。不过,我强烈建议不要使用这种方法 - 不仅它涉及到实现和容易出错的问题,而且你会在这种情况下违背 Hibernate 的范式。
于 2009-08-17T15:22:59.743 回答