当前位置: 首页 > 面试题库 >

手动设置版本字段时的乐观锁定不会引发异常

林祯
2023-03-14
问题内容

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

  1. 注释实体中的版本列:@Version private long version;。通过查看数据库表,我确认该字段正在正确递增。
  2. 当用户请求实体进行编辑时,也发送该version字段。
  3. 当用户在编辑后按下提交时,将version字段作为隐藏字段或其他内容接收。
  4. 服务器端,获取实体的新副本,然后与字段一起更新所需的version字段。像这样:
    User user = userRepository.findOne(id);
    

    user.setName(updatedUser.getName());
    user.setVersion(updatedUser.getVersion());
    userRepository.save(user);

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

因此,我猜测我将不得不手动检查版本不匹配并自己抛出异常。那是正确的方法,还是我错过了什么?


问题答案:

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

例如

这会工作

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()其中,而不是真正设置版本,而是执行版本检查:

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

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

    //.....
}


 类似资料:
  • 存储这些数据后,当需要更新数据时,首先将JSON字符串解析为实体,然后更新属性,然后在Redis中刷新数据。所以Redis中的数据将是最新的数据。 当我们需要将Redis数据保存到MongoDB时,我们首先将JSON字符串解析为实体,然后使用Morphia DAO保存实体,但是我们遇到了这个异常: 我知道这一定是乐观锁的问题。我们如何解决这个并发异常?

  • 我使用SpringDataJPA和Hibernate作为PostgreSQL上的持久性提供者。我试图提供悲观锁定: 我尝试从两个线程中调用< code>findOneAndLock。我认为,如果< code >线程A锁定了对象,那么< code >线程B应该等到锁被释放。而是< code >线程B抛出< code > org . spring framework . ORM . objectopt

  • 众所周知,有两种锁定策略:乐观锁定和悲观锁定 悲观锁定是锁定记录供您独占使用,直到您使用完它。它比乐观锁定具有更好的完整性,但是需要您小心应用程序设计以避免死锁。 也知道,乐观并发控制与多版本并发控制(Oracle或MSSQL-Snapshot/MVCC-RC)不同:乐观与多版本并发控制-差异? 但是,如果在两个事务中都使用OCC(乐观并发控制),会在两个交易之间发生死锁吗? 我们可以说乐观锁通过

  • 我在服务层内部编写了一个更新方法,就像这样,我对所有的CRUD操作都使用Spring-data JpaRepository。 我想对此操作进行乐观锁定,因此我在 实体中添加了一个版本字段。

  • 我想为关系数据库实现乐观锁定。 假设有一个表 我的应用程序获取< code>Jhon用户来更改他的名字 那么,我需要在哪里将所选行的版本与数据库中的行的版本进行比较呢? 数据库事务是否是获取行的现有版本并将其与已获取的记录进行比较的好地方?

  • 问题内容: 我找不到有关MySQL中乐观锁定的任何详细信息。我读到开始事务使两个实体上的更新保持同步,但是,它不会停止两个用户同时更新数据而引起冲突。 显然乐观锁定会解决这个问题吗?这在MySQL中如何应用。是否有SQL语法/关键字呢?还是MySQL具有默认行为? 谢谢你们。 问题答案: 关键是,乐观锁定不是数据库功能,不适用于MySQL或其他功能:乐观锁定是一种使用带有标准指令的DB进行的实践。