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

时间:2009-09-14 18:59:09

标签: java hibernate web-applications optimistic-locking

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

<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隐藏字段中,并随表单一起提交。

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

控制器通过调用包含更新信息(包括版本属性)的DTO的服务方法来响应用户更新请求,然后服务方法依次使用数据访问对象(DAO)来持久化更改: / p>

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(...)复制到实体中的version属性。我在以下论坛中找到了原因:https://forum.hibernate.org/viewtopic.php?f=1&t=955893&p=2418068

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

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

我想请Hibernate检查实例本身的版本属性,而不是仅查看会话缓存。

提前感谢您的回答!

- LES

1 个答案:

答案 0 :(得分:11)

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

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

  1. 最初加载实体,版本= V1
  2. 转移到DTO进入用户界面,返回并准备好保存。
  3. 实体再次加载,版本= V2
  4. 现在有两种可能性:

    1. V1 == V2。 Peachy,你不需要做任何事情。
    2. V1小于V2,表示实体在您编辑时由其他人更新。没有理由尝试将版本设置为V1并尝试保存,因为保存将失败。您可以使用V2保存它(从而覆盖其他人的更改)或现在失败。(不涉及Hibernate)。