如何在前端使用Hibernate乐观锁版本属性?

发布于 2024-08-04 22:06:51 字数 1332 浏览 8 评论 0原文

使用实体的版本属性的乐观锁定工作正常并且易于实现:

<version property="VERSION" type="int" column="EX_VERSION" />

该实体具有以下类型的属性:

private int VERSION;
public int getVERSION() { return VERSION; }
public void setVERSION(int VERSION) { this.VERSION = VERSION; }

到目前为止,一切都很好。现在,服务方法返回上述实体的数据传输对象 (DTO),视图以 HTML 形式显示该对象。对于更新页面,VERSION 属性存储在 HTML 隐藏字段中并与表单一起提交。

目的是使用版本属性来确保如果显示的信息是旧版本,则用户的更新将失败。

控制器通过调用包含更新信息(包括版本属性)的 DTO 的服务方法来响应用户更新请求,而该服务方法又使用数据访问对象 (DAO) 来保存更改:

public void update(SimpleDTO dto) {
    SimplyEntity entity = getSimpleDao().load(dto.getId());
    copyProperties(dto, entity); // all properties, including VERSION copied to entity
    getSimpleDao().update(entity);
}

问题是Hibernate 不尊重通过 copyProperties(...) 复制到实体中的版本属性。我在以下论坛中找到了原因: https:// /forum.hibernate.org/viewtopic.php?f=1&t=955893&p=2418068

简而言之,当调用 load() 时,Hibernate 会在会话缓存中缓存版本属性,而它不会无论它的值随后更改为什么。我同意这是正确的行为,但老板指示我通过 HTML 表单属性传递版本(如果有更好的模式,我很乐意听到)。

我现在正在探索的一种解决方案是在更新发生之前使用 hibernateTemplate.evict(simpleEntity) 设置版本后从会话中逐出实体。我希望这能起作用,但似乎效率不高。

我想要求 Hibernate 检查实例本身的版本属性,而不是仅从会话缓存中检查。

预先感谢您的答复!

-- 莱斯

Optimistic locking using the version attribute for an entity works fine and is easy to implement:

<version property="VERSION" type="int" column="EX_VERSION" />

The entity has a property of the following type:

private int VERSION;
public int getVERSION() { return VERSION; }
public void setVERSION(int VERSION) { this.VERSION = VERSION; }

So far, so good. Now service methods return a data transfer object (DTO) for the entity above, which the views display in HTML. For update pages, the VERSION attribute is stored in an HTML hidden field and submitted with the form.

The intent is to use the version property to ensure that a user's update will fail if the information displayed is accompanied by an old version.

The controller responds to a users update request by invoking a service method with the DTO containing the updated information (including the version property), and the service method in turn uses a data access object (DAO) to persist the changes:

public void update(SimpleDTO dto) {
    SimplyEntity entity = getSimpleDao().load(dto.getId());
    copyProperties(dto, entity); // all properties, including VERSION copied to entity
    getSimpleDao().update(entity);
}

The problem is that the version property copied into the entity by copyProperties(...) is not respected by Hibernate. I tracked down the reason in the following forum: https://forum.hibernate.org/viewtopic.php?f=1&t=955893&p=2418068

In short, when load() is called, Hibernate caches the version property in the session cache and it doesn't matter what it's value is subsequently changed to. I agree that this is the correct behavior, but I have been instructed by Bosses to pass the version via an HTML form property (if there is a better pattern for this, I'd love to hear it).

One solution I am exploring now is to evict the entity from the session after it's version has been set using hibernateTemplate.evict(simpleEntity) before the update happens. I hope this works, but it doesn't seem efficient.

I would like to ask Hibernate to check the version property on the instance itself, rather than only from the session cache.

Thanks in advance for answers!

--
LES

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

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

发布评论

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

评论(1

梦里的微风 2024-08-11 22:06:51

真的需要使用 DTO 吗?如果您传递实际实体,则不会遇到此问题 - 也不必再次加载实体,这对性能来说并不是很好。

但即使您确实有使用 DTO 的正当理由,我也不太明白为什么您会在保存之前尝试更新新重新加载的实体上的版本号。考虑工作流程中可能出现的不同场景:

  1. 实体最初加载,版本 = V1
  2. 它被传输到 DTO,DTO 转到 UI,返回并准备保存。
  3. 实体再次加载,版本 = V2

现在您有两种可能性:

  1. V1 == V2。桃子,你什么都不用做。
  2. V1 小于 V2,这意味着实体在您编辑时已被其他人更新。没有理由尝试将版本设置为 V1 并尝试保存,因为保存将失败。您可以使用 V2 保存它(从而覆盖其他人的更改),也可以立即失败。(不涉及 Hibernate)。

Do you really need to use DTO? You wouldn't have had this problem if you were passing the actual entity around - nor would you have to load the entity again, which isn't exactly great for performance.

But even if you do have a legitimate reason to use DTO, I'm not quite grasping why you would try to update the version number on your freshly reloaded entity prior to saving. Consider different scenarios possible in your workflow:

  1. Entity is loaded initially, has version = V1
  2. It's transferred to DTO which goes to UI, comes back and is ready to be saved.
  3. Entity is loaded again, has version = V2

You have two possibilities now:

  1. V1 == V2. Peachy, you don't have to do anything.
  2. V1 is less than V2, meaning entity was updated by someone else while you were editing it. There's no reason to try to set version to V1 and attempt to save because saving will fail. You can either save it with V2 (thus overriding someone else's changes) or fail now.(without involving Hibernate).
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文