首页 > 解决方案 > 更新同一实体时的 Spring Boot 竞争条件

问题描述

对于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
}

假设如果有 2 个请求同时进入,则 A-1 和 B-1 行同时执行,然后是 A-2 和 B-2,然后是 A-3 和 B-3。

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

标签: hibernatespring-bootspring-data-jpa

解决方案


强烈建议在每个服务中使用@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.

推荐阅读