SpringBoot + MyBatis-Plus 并发更新同一行数据不丢失的解决方案 (不使用乐观锁)
在不使用乐观锁的情况下,保证并发更新同一行数据不丢失的方法是使用悲观锁,即在事务中使用 'SELECT ... FOR UPDATE' 语句锁定需要更新的数据行,确保在事务提交前其他事务无法更新该行数据。
以下是一个使用 SpringBoot + MyBatis-Plus 实现悲观锁的示例代码:
- 创建一个实体类 User,表示用户信息:
@Data
public class User {
private Long id;
private String name;
private Integer age;
private Integer version;
}
- 创建一个 UserMapper 接口,定义对 User 表的操作:
public interface UserMapper extends BaseMapper<User> {
@Select('SELECT * FROM user WHERE id = #{id} FOR UPDATE')
User selectForUpdate(Long id);
}
- 在 Service 层的更新方法中使用悲观锁:
@Service
public class UserService {
@Autowired
private UserMapper userMapper;
@Transactional
public void update(User user) {
// 使用悲观锁锁定需要更新的数据行
User lockedUser = userMapper.selectForUpdate(user.getId());
// 更新数据行
lockedUser.setName(user.getName());
lockedUser.setAge(user.getAge());
lockedUser.setVersion(lockedUser.getVersion() + 1);
userMapper.updateById(lockedUser);
}
}
在以上代码中,使用 @Transactional 注解标记事务,在事务中使用 UserMapper 接口中定义的 selectForUpdate 方法锁定需要更新的数据行,并在事务中更新该行数据。由于该行数据被锁定,其他事务无法更新该行数据,从而保证了并发更新同一行数据不丢失的问题。
需要注意的是,使用悲观锁会影响系统性能,因为需要在数据库中加锁并等待其他事务释放锁。在实际应用中应根据业务场景和系统性能需求选择合适的锁机制。
原文地址: https://www.cveoy.top/t/topic/nCQe 著作权归作者所有。请勿转载和采集!