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

时间:2022-02-12 01:20:22

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.

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

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.

目的是使用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:

控制器通过使用包含更新信息(包括版本属性)的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);
}

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

问题是copyProperties(…)复制到实体中的版本属性不受Hibernate的尊重。我在下面的论坛上找到了原因:https://forum.hibernate.org/viewtopic.php?

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

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

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.

我现在正在探索的一个解决方案是,在更新发生之前,将该实体从会话中移除,然后使用hibernatetemplate .逐出(simpleEntity)。我希望这是可行的,但似乎不太有效。

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

我希望Hibernate检查实例本身的version属性,而不是只检查会话缓存。

Thanks in advance for answers!

谢谢你的回答!

-- LES

- - -莱斯

1 个解决方案

#1


10  

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.

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

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:

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

  1. Entity is loaded initially, has version = V1
  2. 实体是最初加载的,具有version = V1
  3. It's transferred to DTO which goes to UI, comes back and is ready to be saved.
  4. 它被转移到DTO,转到UI,返回并准备保存。
  5. Entity is loaded again, has version = V2
  6. 实体再次被加载,版本= V2

You have two possibilities now:

你现在有两种可能:

  1. V1 == V2. Peachy, you don't have to do anything.
  2. V1 = = V2。桃子,你什么都不用做。
  3. 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).
  4. V1小于V2,意味着当你在编辑实体时,其他人更新了实体。没有理由试图将版本设置为V1并尝试保存,因为保存会失败。您可以使用V2保存它(从而覆盖其他人的更改),也可以现在失败。(不包括Hibernate)。

#1


10  

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.

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

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:

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

  1. Entity is loaded initially, has version = V1
  2. 实体是最初加载的,具有version = V1
  3. It's transferred to DTO which goes to UI, comes back and is ready to be saved.
  4. 它被转移到DTO,转到UI,返回并准备保存。
  5. Entity is loaded again, has version = V2
  6. 实体再次被加载,版本= V2

You have two possibilities now:

你现在有两种可能:

  1. V1 == V2. Peachy, you don't have to do anything.
  2. V1 = = V2。桃子,你什么都不用做。
  3. 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).
  4. V1小于V2,意味着当你在编辑实体时,其他人更新了实体。没有理由试图将版本设置为V1并尝试保存,因为保存会失败。您可以使用V2保存它(从而覆盖其他人的更改),也可以现在失败。(不包括Hibernate)。