如何在JBoss下以一致的状态维护EntityManager的Hibernate缓存?

时间:2009-08-17 13:54:52

标签: hibernate caching jboss entitymanager

我们正在使用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()似乎是浪费资源。

1 个答案:

答案 0 :(得分:1)

阿尔乔姆,

您的问题似乎是recurring theme: - )

虽然我明白你以前给过的答案(包括我的答案)可能不是你所希望的,但它们不会改变:

  • 实体管理器映射到Hibernate会话,通常需要是短暂的。 Here是对Hibernate会话相关的工作单元,事务和范围的一个很好的解释,看看你以前没有看过它。
  • 如果您的应用始终持有实体经理,则需要认真考虑更改该策略;如果你只是在一些你需要长时间交易而不是使用refresh()方法的地方做这件事,肯定是所有邪恶中较少的。
  • 与具有群集实现的second level cache不同,会话级缓存在不同会话(实体管理器)按设计之间不同步,并且同一实体的并发更新通过{{处理3}}由Hibernate或应用程序级锁定提供。
  • 理论上(如果你的ORM访问分离得足够好),您可以维护各个实体经理所拥有的实体的自己的缓存(如果需要可以集群);您需要为每个注册相应的optimistic locking以保持缓存同步。我强烈建议不要采用这种方法 - 不仅仅涉及实现和容易出错,而且你会反对Hibernate的范例。