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

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

问题描述

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


  1. 在实体中注释版本列: @Version private long版本; 。我确认,通过查看数据库表,该字段正在递增。

  2. 当用户请求实体进行编辑时,发送版本
  3. 当用户在编辑后按下提交时,将版本字段接收为隐藏字段或其他内容。

  4. 服务器端,获取实体的新副本,然后更新所需字段以及版本字段。像这样:

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


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



所以,我猜测我必须手动检查版本不匹配,并自己抛出异常。这是否是正确的方式,或者我错过了什么?

解决方案

不幸的是,(至少对于Hibernate)手动添加c $ c> @版本字段不会使其成为另一个版本。即乐观并发检查是根据读取实体时检索到的版本值来完成的,而不是在更新时实体的版本字段。

例如。



这将起作用

  Foo foo = fooRepo.findOne(id ); //假设版本是2这里
foo.setSomeField(....);

//假设在这个时间点其他人改变了DB中的记录,
//并将DB中的版本增加到3

fooRepo.flush() ; //强制更新,然后抛出开放式并发异常

然而,这不起作用

  Foo foo = fooRepo.findOne(id); //假设版本是2这里
foo.setSomeField(....);
foo.setVersion(1);
fooRepo.flush(); //强制更新,没有乐观并发异常
// Coz Hibernate足够聪明,足以使用原始2进行比较

有一些方法可以解决此问题。最直接的方法可能是通过自己实施乐观并发检查。我曾经有一个util来完成DTO to Model数据填充,我已经在那里安装了版本检查逻辑。另一种方法是将逻辑放在 setVersion()中,而不是真的设置版本,它会进行版本检查:

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

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

// .....
}


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

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

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?

解决方案

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.

e.g.

This will work

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

However this will not work

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

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天全站免登陆