手动设置版本字段时乐观锁定不抛出异常 [英] Optimistic locking not throwing exception when manually setting version field

查看:13
本文介绍了手动设置版本字段时乐观锁定不抛出异常的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个使用 Spring Data JPA 的 Spring Boot 1.3.M1 Web 应用程序.对于乐观锁定,我正在执行以下操作:

I have a Spring Boot 1.3.M1 web application using Spring Data JPA. For optimistic locking, I am doing the following:

  1. 注释实体中的版本列:@Version private long version;.我通过查看数据库表确认该字段正确递增.
  2. 当用户请求编辑实体时,同时发送 version 字段.
  3. 当用户在编辑后按下提交时,接收 version 字段作为隐藏字段或其他东西.
  4. 服务器端,获取实体的新副本,然后更新所需字段以及 version 字段.像这样:

  1. Annotate the version column in the entity: @Version private long version;. I confirmed, by looking at the database table, that this field is incrementing properly.
  2. When a user requests an entity for editing, sending the version field as well.
  3. When the user presses submit after editing, receiving the version field as a hidden field or something.
  4. Server side, fetching a fresh copy of the entity, and then updating the desired fields, along with the version field. Like this:

User user = userRepository.findOne(id);
user.setName(updatedUser.getName());
user.setVersion(updatedUser.getVersion());
userRepository.save(user);

我原以为版本不匹配时会抛出异常.但事实并非如此.谷歌搜索,我发现一些帖子说我们不能设置附加实体的 @Vesion 属性,就像我在上面的第三个语句中所做的那样.

I was expecting this to throw exception when the versions wouldn't match. But it doesn't. Googling, I found some posts saying that we can't set the @Vesion property of an attached entity, like I'm doing in the third statement above.

所以,我猜我必须手动检查版本不匹配并自己抛出异常.这是正确的方法,还是我遗漏了什么?

So, I am guessing that I'll have to manually check for the version mismatch and throw the exception myself. Would that be the correct way, or I am missing something?

推荐答案

不幸的是,(至少对于 Hibernate)手动更改 @Version 字段不会使其成为另一个版本".即乐观并发检查是针对读取实体时检索到的版本值进行的,而不是更新时实体的版本字段.

Unfortunately, (at least for Hibernate) changing the @Version field manually is not going to make it another "version". i.e. Optimistic concurrency checking is done against the version value retrieved when entity is read, not the version field of entity when it is updated.

例如

这会起作用

Foo foo = fooRepo.findOne(id);  // assume version is 2 here
foo.setSomeField(....);

// Assume at this point of time someone else change the record in DB, 
// and incrementing version in DB to 3

fooRepo.flush();  // forcing an update, then Optimistic Concurrency exception will be thrown

但是这行不通

Foo foo = fooRepo.findOne(id);  // assume version is 2 here
foo.setSomeField(....);
foo.setVersion(1);
fooRepo.flush();  // forcing an update, no optimistic concurrency exception
                  // Coz Hibernate is "smart" enough to use the original 2 for comparison

有一些方法可以解决这个问题.最直接的方法可能是自己实现乐观并发检查.我曾经有一个实用程序来执行DTO 到模型"数据填充,并且我已经将版本检查逻辑放在那里.另一种方法是将逻辑放在 setVersion() 中,它不是真正设置版本,而是进行版本检查:

There are some way to workaround this. The most straight-forward way is probably by implementing optimistic concurrency check by yourself. I used to have a util to do the "DTO to Model" data population and I have put that version checking logic there. Another way is to put the logic in setVersion() which, instead of really setting the version, it do the version checking:

class User {
    private int version = 0;
    //.....

    public void setVersion(int version) {
        if (this.version != version) {
            throw new YourOwnOptimisticConcurrencyException();
        }
    }

    //.....
}

这篇关于手动设置版本字段时乐观锁定不抛出异常的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆