如何改变Hibernate的自动持久化策略

发布于 2024-09-02 21:07:25 字数 714 浏览 6 评论 0原文

我刚刚注意到,在调用任何 save()update() 方法之前,Hibernate 实体会自动保存到数据库(或至少缓存)。对我来说,这是一个非常奇怪的默认行为 - 但是好吧,只要我可以禁用它,就可以了。

我遇到的问题是,仅当数据库中的实体仍具有检索它时的状态(状态“1”)时,我才想更新实体的状态(从状态“1”到状态“2”)。这是为了消除当另一台服务器更新同一对象时的并发问题。因此,我创建了一个自定义 NamedQuery,它仅在实体处于预期状态“1”时才会更新该实体。这是一些伪代码:

// Get the entity
Entity item = dao.getEntity(); 
item.getState(); // == 1

// Update the entity
item.setState(2); // Here is the problem, this effectively changes the
                  // state of my entity breaking my query that verifies
                  // that state is still == 1.

dao.customUpdate(item); //Returns 0 rows changes since state != 1.

如何确保设置器不会更改缓存/数据库中的状态?

I just noticed that Hibernate entities are automatically persisted to the database (or at least to cache) before I call any save() or update() methods. To me this is a pretty strange default behavior — but ok, as long as I can disable it, it's fine.

The problem I have is that I want to update my entity's state (from a state "1" to state "2") only if the entity in the database still has the state it had when I retrieved it (state "1"). This is to eliminate concurrency issues when another server is updating this same object. For this reason, I have created a custom NamedQuery that will only update the entity if it is in the expected state "1". Here is some pseudo-code:

// Get the entity
Entity item = dao.getEntity(); 
item.getState(); // == 1

// Update the entity
item.setState(2); // Here is the problem, this effectively changes the
                  // state of my entity breaking my query that verifies
                  // that state is still == 1.

dao.customUpdate(item); //Returns 0 rows changes since state != 1.

How do I make sure the setters don't change the state in cache/db?

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

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

发布评论

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

评论(2

白馒头 2024-09-09 21:07:25

Hibernate 内置了对您想要实现的目标的支持 - 它支持使用版本 ID 或时间戳的乐观锁定。如果您尝试保存对象并且底层数据已更改,hibernate 会抛出异常。您可以捕获此异常并根据需要进行处理 - 忽略更新、重试或任何有意义的操作。

请参阅乐观并发控制

编辑:我不清楚您的更新查询是如何工作的,但是如果您想继续手动执行此操作,您可以在检索对象后将其从会话中逐出。这为您提供了对象在检索时的快照,您可以独立于数据库/缓存进行修改。您可以将其作为比较的一侧传递到自定义更新查询中,另一侧作为持久值。当查询选择/更新实体时,将从数据库中重新读取该实体,而不是从已驱逐的对象中读取。然后,您的更新查询可以将其与您驱逐/修改的值(作为参数传递)进行比较,以查看是否应该完成更新。

请参阅 Session.evict()

Hibernate has built in support for what you are aiming to achieve - it supports optimistic locking using version ids or timestamps. If you try to save an object and the underlying data has changed, hibernate throws an exception. You can catch this exception and handle as necessary - ignore the update, retry or whatever makes sense.

See Optimistic Concurrency Control

EDIT: I'm not clear on how your update query works, but if you want to continue doing this by hand, you can evict your object from the session after retreiving it. This gives you a snapshot of the object as it was at retrieval time that you can modify independent from the db/cache. You can pass it into your custom update query as one side of the comparison, the other side being the persisted value. When the query selects/updates the entity, it will be re-read from the database, not from your evicted object. Your update query can then compare this with your evicted/modified value (passed as a parameter) to see if the update should be done or not.

See Session.evict()

我不是你的备胎 2024-09-09 21:07:25

您应该设置会话的刷新模式。这样,会话实体只有在执行 session#flush(); 后才会被持久化。

如果您希望更新会话缓存或数据库,请执行以下操作:

Bean bean = session.get(Bean.class, bean.getId());
session.setFlushMode(FlushMode.COMMIT);
// Make some changes to bean object.
Bean bean2 = session.get(Bean.class, bean.getId());
Assert.assertFalse(bean.equals(bean1)); // Assuming equals and hashcode are implemented

You should set the flush mode of your session. That way the session entities will only be persisted after executing session#flush();

If you want the session cache or db to be updated, do something like this:

Bean bean = session.get(Bean.class, bean.getId());
session.setFlushMode(FlushMode.COMMIT);
// Make some changes to bean object.
Bean bean2 = session.get(Bean.class, bean.getId());
Assert.assertFalse(bean.equals(bean1)); // Assuming equals and hashcode are implemented
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文