【问题标题】:Spring data PESSIMISTIC_WRITE returns old DB valueSpring data PESSIMISTIC_WRITE 返回旧的 DB 值
【发布时间】:2017-07-20 16:26:34
【问题描述】:

我的界面中有这个扩展 CrudRepository 的方法:

@Lock(LockModeType.PESSIMISTIC_WRITE)
Voucher findTop1ByUsedFalseAndProductOrderByIdAsc(Product product);

还有这个组件:

@Component
@Transactional
public class VoucherFetchComponent {
    @Autowired
    private VoucherRepository voucherRepository;
public Voucher fetch(Product product) {
    Voucher voucher=voucherRepository.findTop1ByUsedFalseAndProductOrderByIdAsc(product);
    if(voucher==null)
       return null;
    voucher.setUsed(true);
    voucherRepository.save(voucher);
    return voucher;
}
}

问题是同时执行 fetch() 方法。 (假设我的数据库中只剩下一张优惠券)

我的期望:

1- 服务 A 和 B 调用 VoucherFetchComponent 的 fetch() 方法

2- 服务 A(或 B)锁定行,更新其中一个字段并返回

3- 其他服务现在可以访问被锁定的行。但是现在查询不匹配给定的条件(used=false),所以它返回 null。

我得到了什么

1 和 2 同上

3- 其他服务返回具有参数 (used=false) 但之前已更新的旧对象!

【问题讨论】:

    标签: java spring spring-data persistence


    【解决方案1】:

    如果您仔细查看 @Lock 的 javadoc,它会指出:

    用于指定执行时要使用的 LockModeType 的注解 查询。

    所以锁只有在查询执行期间才有效..查询完成后..锁被释放。它在整个事务期间并不像您预期​​的那样处于活动状态。

    我建议使用标准锁定机制:

    VoucherRepository

    public void lock(Voucher voucher, LockModeType lockType){
    
    entityManager.lock(voucher, lockType);
    

    VoucherFetchComponent

    public Voucher fetch(Product product) {
        Voucher voucher=voucherRepository.findTop1ByUsedFalseAndProductOrderByIdAsc(product);
        if(voucher==null)
           return null;
        voucherRepository.lock(voucher, LockModeType.PESSIMISTIC_WRITE);
        voucher.setUsed(true);
        voucherRepository.save(voucher);
        return voucher;
    }
    

    一旦事务完成,锁就会被释放。

    【讨论】:

    • 没有进展。当第二个服务想要通过调用 save() 方法来更新实体时,它会抛出 OptimisticLockException。我希望 findTop1ByUsedFalseAndProductOrderByIdAsc 方法不返回相同的值
    • 好吧,如果一个方法试图查询一个锁定的实体,你将得到锁定异常......处理这些异常的标准方法是在事务方法周围放置一个 try{ catch{ 块并重试出现异常(事务无论如何都会回滚,因此您需要启动一个新事务)。一旦锁被释放,第二个服务将进入该方法并获得空值。
    • 事务完成,锁似乎被释放,但 findTop1ByUsedFalseAndProductOrderByIdAsc(..) 仍然返回旧对象..
    猜你喜欢
    • 1970-01-01
    • 2022-07-21
    • 2022-10-04
    • 2015-07-31
    • 2019-12-13
    • 2016-06-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多