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

Posted

技术标签:

【中文标题】前端如何使用Hibernate乐观锁版本属性?【英文标题】:How to use the Hibernate optimistic locking version property on the front end? 【发布时间】:2010-11-28 05:47:54 【问题描述】:

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

<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);

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

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

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

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

提前感谢您的回答!

-- LES

【问题讨论】:

从会话中驱逐()实体有效。 :) 保持开放,看看是否有我有见地的答案...... 【参考方案1】:

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

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

    最初加载实体,版本 = V1 它已转移到 DTO,然后转到 UI,然后返回并准备保存。 实体再次加载,版本 = V2

你现在有两种可能:

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

【讨论】:

1.可能需要重新加载,因为 DTO 可能不完全包含所有实体字段,只是一个子集。 2. 正如评论(也可以在forum.hibernate.org/viewtopic.php?t=977889a 底部的链接处阅读),evict 可以在这里提供帮助。

以上是关于前端如何使用Hibernate乐观锁版本属性?的主要内容,如果未能解决你的问题,请参考以下文章

Hibernate 乐观锁(Optimistic Locking)

乐观锁的实现

Hibernate 再接触 悲观锁和乐观锁

hibernate基础24:乐观锁和悲观锁

hibernate基础24:乐观锁和悲观锁

Optimistic Locking(乐观锁)