如何在JBoss下与Hibernate保持EntityManager的缓存状态一致?

发布于 2024-08-02 21:57:49 字数 547 浏览 4 评论 0原文

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

We are running JBoss with Hibernate and are having this issue.

When a session bean uses an EntityManager to find an entity, it may already exist in the EntityManager's cache and it's state may be already outdated. If the code uses such an entity to make decisions, it may make wrong decisions that would produce bugs.

Here is an example case.

HTTP request 1. A session bean creates an entity instance and stores it with field "A" set to value 1. The persisted entity gets ID = 4.

HTTP request 2. A session bean looks up an entity with ID = 4, sets its field "A" to value 2 and saves it.

HTTP request 3. A session bean looks up an entity with ID = 4 and checks it's field "A". If the value is 1 it does one thing, if it is 2 it does another thing.

In case if the EM in request 3 happens to be the same as in request 1, an undesired behavior occurs. I have tested this and got approx. 10% cases of failure.

So the question is - how to avoid this? Calling em.refresh() or em.clear() each time I have to ensure the entity is up to date seems to be a waste of resources.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

南七夏 2024-08-09 21:57:49

Artem,

这似乎是重复出现 主题在你的问题中

:-)我知道您之前给出的答案(包括我的)可能不是您所希望的,它们不会改变:

Artem,

This seems to be a recurring theme among your questions :-)

While I understand that answers you've been given before (including mine) may not be what you were hoping for, they're not going to change:

  • Entity Manager is a mapped to Hibernate session and generally needs to be short-lived. Here is a good explanation of unit of work, transaction and scope pertaining to Hibernate sessions, take a look if you haven't seen it before.
  • If your application is consistently holding on to Entity Managers, you need to seriously consider changing that strategy; if you're just doing it in a few places where you really need to have long transactions than using refresh() method there is definitely the lesser of all evils.
  • Unlike the second level cache which has clustered implementations, session-level cache is not synchronized among diferent sessions (entity managers) by design and concurrent updates to the same entity are handled via optimistic locking provided by Hibernate or application-level locking.
  • You could in theory (provided your ORM access is separated well enough) maintain your own cache (clusterable if needed) of entities held by various Entity Managers; you would need to register appropriate event listeners with each to keep your cache in sync. I would strongly advice against this approach, though - not only it's rather involved to implement and bug-prone, but you'd be going against Hibernate's paradigm with this.
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文