【问题标题】:Multi JPA transaction inner one method多 JPA 事务内一种方法
【发布时间】:2020-03-28 17:40:35
【问题描述】:

我有一个例子,它需要通过条件外循环回滚一些方法内循环。 我使用 EntittyManager 和 @Transactional。 因为循环中的逻辑很复杂,所以我不想进入 2 循环。 如何实现回滚、提交?

@Service
@Transactional
public class StudentServiceImpl implement StudentService {

    @Transactional(propagation = Propagation.REQUIRES_NEW)
    public boolean execute(List<ADto> adtoList) {
      boolean a = true;
      for(ADto dto : adtoList) {
          boolean a =  method1(dto); // call to sub method2, method3 to insert data into A, B table
          if(a == false) {
             break;
          }
          method4(); // do insert data into D, E table
          method5(); // do update into F table

       }
    if(a == false) {
       // need rollback all inserted data in A, B table which is inserted in method1, method2, method3 (of all loop element)
       // still commit all inserted data at method4(), method5()  (of all loop element)
     }

【问题讨论】:

    标签: spring-boot jpa transactions entitymanager


    【解决方案1】:

    从问题陈述看来,

    method1()、method2() 和 method3() 调用应该在当前 txn 中运行。

    method4() 和 method5() 应该在各自独立的 txn(s) 上运行。

    当 method1() 返回 false 时,将执行中断,并且 RuntimeException 将回滚通过 method1() 事务插入到该点的任何内容。

    method4() 和 method5() 数据将保留在它们自己的独立事务中。

    阅读更多

    PROPAGATION_REQUIRES_NEW = 3;如果 DataSourceTransactionObject T1 是 方法 M1 已经开始并且正在进行中(执行方法 M1) . 如果另一个方法 M2 开始执行,则 T1 暂停 具有新 DataSourceTransactionObject T2 的方法 M2 的持续时间 M2.M2 在自己的事务上下文中运行

    还要注意,自调用(目标对象内的方法调用)不会导致事务。您需要对 method4() 和 method5() 上的事务进行自我注入才能工作。内容如下

             @Service @Transactional
                public class StudentServiceImpl implements StudentService {
    
                   @Autowired
                   private StudentService self;   //self injection ;
    
                   @Transactional(propagation= Propagation.REQUIRES_NEW)
                   public boolean execute(List<ADto> adtoList) {
                    boolean a = true;
                    for(ADto dto : adtoList) {
                      boolean a = method1(dto); // uses the current txn.
                      if(a == false) {
                          break;
                      }
                      self.method4(); // do insert data into D, E table
                      self.method5(); // do update into F table
                    }
                    if(!a) {
                      throw new RuntimeException("Rollback Txn for method1");
                    }
                   }
    
    
                   @Transactional(propagation= Propagation.REQUIRES_NEW)
                   public void method4() {
    
                   }
    
                   @Transactional(propagation= Propagation.REQUIRES_NEW)
                   public void method5() {
    
                   }
                }
    

    method4() 和 method5() 用 @Transactional(propagation = Propagation.REQUIRES_NEW) 注释并在代理上调用

    还可以从文章 https://www.byteslounge.com/tutorials/spring-transaction-propagation-tutorial 中了解 REQUIRES_NEW 行为

    【讨论】:

    • 谢谢,但有几点如下: 1.“还要注意自我调用(目标对象内的方法调用)不会导致事务。你需要做一个自我为方法1()上的事务注入工作“=>对不起,但我输入错误,不是“扩展StudentService”,正确的是“实现StudentService”。我又更新了2.顺便问一下,method1(dto)在哪里调用? (注:该方法调用子method2、method3向A、B表插入数据。
    • 这是一个复制和粘贴问题。根据您的评论修改代码
    • 谢谢,但我需要在 adtoList 的所有先前元素中插入的回滚数据,而不仅仅是当前元素。
    • 修改了答案。
    • 我的问题是需要在外部按条件回滚(例如:a == false),而不仅仅是在发生异常时回滚。所以我认为你的建议并没有解决我的问题。我打算添加 2 个实体管理器来控制 2 个事务
    猜你喜欢
    • 2015-01-31
    • 2011-11-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-06-01
    • 2019-05-17
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多