首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Spring数据PESSIMISTIC_WRITE返回旧的DB值

Spring数据PESSIMISTIC_WRITE返回旧的DB值
EN

Stack Overflow用户
提问于 2017-03-01 11:08:56
回答 1查看 1.2K关注 0票数 6

我的接口中有这个方法,它扩展了CrudRepository:

代码语言:javascript
复制
@Lock(LockModeType.PESSIMISTIC_WRITE)
Voucher findTop1ByUsedFalseAndProductOrderByIdAsc(Product product);

这一构成部分:

代码语言:javascript
复制
@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()方法。(假设我的DB中只剩下1张凭单)

我所期望的:

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

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

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

我得到了什么,

1和2就像上面一样

3-另一个服务返回具有参数(used=false)的旧对象,但它以前已经更新过了!

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2017-03-01 11:27:05

如果仔细查看@Lock的javadoc,它会声明:

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

因此,锁只有在查询执行期间才处于活动状态。查询完成后..。锁被释放了。在整个事务的持续时间内,它并不像您所期望的那样处于活动状态。

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

VoucherRepository

代码语言:javascript
复制
public void lock(Voucher voucher, LockModeType lockType){

entityManager.lock(voucher, lockType);

VoucherFetchComponent

代码语言:javascript
复制
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;
}

事务完成后,锁将被释放。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/42530115

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档