带有悲观锁的过程中的Spring JPA事务提交

Posted

技术标签:

【中文标题】带有悲观锁的过程中的Spring JPA事务提交【英文标题】:Spring JPA Transactional commit during process with Pessimistic lock 【发布时间】:2022-01-17 22:30:54 【问题描述】:

我需要使用悲观锁执行批处理操作,以便在此操作期间没有其他人可以读取或写入该行。但是我想在每批之后增加页码,这样如果事务失败或实例死亡,我将从最后一页继续。但是使用下面的代码,在所有批次完成之前它不会更新页面,因此在重新启动作业时,它从 page=0 开始处理。

@Transactional
public void process(long id) 
    Entity entity = repo.findById(id);
    processBatch(entity);


void processBatch(Entity entity) 
    int totalPages = otherMicroService.getTotalPages(id);
    int lastPage = entity.getPage();
    for(int page=lastPage; i<totalPages; i++) 
        doOperation();
        entity.setPage(page);
        repo.save(entity);
    



@Lock(LockModeType.PESSIMISTIC_WRITE)
Optional<Entity> findById(int id);

有没有办法在启用 PESSIMISTIC_WRITE 的情况下在每批之后更新页面?

提前致谢。

【问题讨论】:

【参考方案1】:

我会将@Transactional(propagation = Propagation.REQUIRES_NEW) 添加到processBatch,以便在每次迭代时提交数据(顺便说一句,savesaveAndFlush 在这种情况下工作方式相同)。

请注意,添加此注解后,processBatch 方法需要移动到单独的 bean(或应进行 bean 的自注入),以使 Spring AOP 正常工作。

【讨论】:

你的意思是@Transactional on process() 和@Transactional(propagation = Propagation.REQUIRES_NEW) on processesBatch(),两个注解? @Lock(LockModeType.PESSIMISTIC_WRITE) 不会阻止新事务的写入吗? 试过了。仍然没有发生更新。我相信这是因为锁定:@Lock(LockModeType.PESSIMISTIC_WRITE)。解决这个问题的任何替代方法! 抱歉,我的意思是使用“REQUIRES_NEW”方法将“for”语句中的内部代码提取到单独的 bean。此外,您可能需要为外部方法设置 @Transaction(noRollbackFor=Exception.class) 之类的东西,以禁用已处理批次的回滚 谢谢。但它仍然是一样的。我可以在工作期间甚至在其间终止工作之后看到更新的值。

以上是关于带有悲观锁的过程中的Spring JPA事务提交的主要内容,如果未能解决你的问题,请参考以下文章

Spring Data JPA / Hibernate中锁的范围是什么?

悲观锁和乐观锁的区别以及实现方式

Spring JPA无法提交jdbc事务的解决办法

Spring data Jpa,Mybatis,读写锁,@Lock 使用

mysql中的乐观锁和悲观锁

测试期间的Spring Boot JPA事务 - 不会在插入时抛出密钥违例异常