更新相同实体时的Spring Boot竞争条件

时间:2020-04-19 14:35:40

标签: hibernate spring-boot spring-data-jpa

对于Spring Boot,我了解如果我有一个说减少用户平衡的功能,我们可以在服务方法中使用如下所示的@Transactional注释:

@Transactional
public void reduceBalance(long userId, BigDecimal usage) {
    ...
}

但是我的问题不是要在特定功能上放置控件,我想知道以下内容:

public void updateAge(long userId, int newAge) {
    User theUser = userRepository.findById(userId).orElse(null); // Line A-1
    theUser.setAge(newAge); // Line A-2
    userRepository.save(theUser); // Line A-3
}

public void updateName(long userId, String newName) {
    User theUser = userRepository.findById(userId).orElse(null); // Line B-1
    theUser.setName(newName); // Line B-2
    userRepository.save(theUser); // Line B-3
}

假设两个请求完全同时出现,则同时执行第A-1和B-1行,然后依次执行A-2和B-2,然后是A-3和B-3。

B-3是否会覆盖A-2的更改?如果是,这是否意味着我们应该在几乎每个服务中都使用@Transactional批注,还是实际上有更好的设计?

1 个答案:

答案 0 :(得分:1)

强烈建议在每个服务中使用@Transaction,但如果您想通过不同的方式进行管理, 其他方法是使用@Version批注

 Specifies the version field or property of an entity class that
 serves as its optimistic lock value.  The version is used to ensure
 integrity when performing the merge operation and for optimistic
 concurrency control.