使用 REQUIRES_NEW 传播将交易从一个函数传递到另一个函数

问题描述 投票:0回答:1

我有 @Transactional 注释的问题,我无法解决。 据我了解,如果没有活动交易,则使用 Propagation.REQUIRED 现有交易或创建新交易。
并且使用 Propagation.REQUIRES_NEW 创建新事务,并且应该在返回其他现有事务之前提交。

我想实现以下目标:

当我循环浏览任务列表时 如果在completeTaskOrDoSomethingElse函数中发生任何错误
恢复该函数中发生的所有事务,不要恢复任务列表中其他任务的事务。

如果completeTask()函数中发生错误,则从该函数恢复事务
如果 sendTaskAfterInsertToOtherService() 中发生错误,则恢复在 sendTaskAfterInsertToOtherService() 和completeTask() 函数中发生的事务

不知道如何执行此操作,因为必须提交任务才能从数据库获取数据,并且据我所知,事务是否已提交,无法恢复。

如有任何帮助,我们将不胜感激,我将提供任何其他信息


     mainFunction()
  {
    for(task in listOfTasks)
        completeTaskOrDoSomethingElse(task);
  }
  
  @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRES_NEW)
  completeTaskOrDoSomethingElse(Task task)
  {
     Task newTask= completetask(task);
    
     sendTaskAfterInsertToOtherService(task.getId());

   //if error happens in sendTaskAfterInsertToOtherService() revert data from both 
//sendTaskAfterInsertToOtherService() and completetask() functions

  
  }
  
  @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRES_NEW)
  completeTask()
  {
    //insert task into db
  }
  
    //if completeTask() doesnt have REQUIRES_NEW propagination transaction wont be commited to db and when i try to get task by id exception happens because 
    task is not saved to db
 sendTaskAfterInsertToOtherService(task.getId())
     {
        task = taskDao.getById()
        
        //insert to db
        callOtherService(task);
     
     }
    
java spring transactions spring-transactions
1个回答
0
投票

使用Spring Transaction时,即使使用REQUIRES_NEW传播属性,也会回滚到父事务,因为设置了相同的事务管理器。

有两种方法可以实现您想要的场景。

  1. 为每笔交易设置不同的交易管理器
  • 声明并注入一个单独的
    PlatformTransactionManager
    bin 并将其设置为
    @Transactional(value = "anotherTransaction")
    以用于您想要独立执行的交易
    1. 使用
      TransactionEventListener
  • 实现一个 EventListner 来执行您想要在子事务中执行的任务。如果通过
    AFTER_COMIT
    属性实现,则子事务回滚时,父事务不受影响。
© www.soinside.com 2019 - 2024. All rights reserved.