我有一个使用Spring Data JPA的Spring Boot 1.3.M1 Web应用程序。对于乐观锁定,我正在执行以下操作:
@Version private long version;
version
User user = userRepository.findOne(id);
user.setName(updatedUser.getName()); user.setVersion(updatedUser.getVersion()); userRepository.save(user);
我期望当版本不匹配时会抛出异常。但事实并非如此。谷歌搜索,我发现一些帖子说我们不能设置@Vesion附加实体的属性,就像我在上面的第三条语句中所做的那样。
@Vesion
因此,我猜测我将不得不手动检查版本不匹配并自己抛出异常。那是正确的方法,还是我错过了什么?
不幸的是,(至少对于Hibernate而言)@Version手动更改字段不会使它成为另一个“版本”。即乐观并发检查是针对读取实体时获取的版本值而不是针对实体更新时的版本字段进行的。
@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()其中,而不是真正设置版本,而是执行版本检查:
setVersion()
class User { private int version = 0; //..... public void setVersion(int version) { if (this.version != version) { throw new YourOwnOptimisticConcurrencyException(); } } //..... }