【问题标题】:Rollback all nested transactions when outer one is marked for rollback当外部事务标记为回滚时回滚所有嵌套事务
【发布时间】:2012-06-25 17:00:33
【问题描述】:

我有两个用@Transactional 注释的方法。第二种方法在第一种方法中嵌套的某个地方调用。

现在我希望发生以下行为:

  • 每次输入第二个嵌套方法时,都会生成一个新的嵌套方法 应该创建事务。当该交易被标记为 回滚,只有那个事务应该回滚。
  • 但是当 外部方法的事务被标记为回滚,每个 内部的嵌套事务——无论它是否标记为回滚—— 应该回滚。

如何设置Propagation 值才能实现这样的功能?


P。 S.:我使用的是HibernateTransactionManager

【问题讨论】:

    标签: java spring transactions rollback propagation


    【解决方案1】:

    您需要使用NESTED。请注意,此传播模式使用 JDBC SavePoints 来实现此行为,因此嵌套行为仅在事务只是 JDBC 连接的包装器时才有效。它不适用于 JTA 事务。有关详细信息,请参阅Spring documentation

    【讨论】:

    • HibernateTransactionManager 似乎也不完全支持嵌套事务。
    • JB Nizet,您知道在 JTA 下实现该行为的任何方法吗?我陷入了这个问题:stackoverflow.com/questions/28090428/…
    【解决方案2】:

    应该澄清 Java 事务中的默认行为。除非父提交,否则所有嵌套事务都不会提交。阅读这里http://en.wikibooks.org/wiki/Java_Persistence/Transactions

    【讨论】:

      【解决方案3】:

      我建议在单独的线程中实现此类功能,即您希望在嵌套事务中启动的方法 - 只需在单独的线程中启动它们即可。它可能看起来像下面的伪代码:

      //SomeService 
      // Here we start an external transaction
      @Transactional
          int processAllInTransaction() {
              List<Integer> jobIds = jobService.getJobs();
              if (!jobIds.isEmpty()) {
                  new Thread(new Runnable() {
                      @Override
                      public void run() {
                          jobIds.forEach(jobId ->
                                  //Execute eveything in external transaction   
                                  threadPool.execute(jobId)
                          );
                      }
                  }).start();
      
              } 
              return jobIds.size();
          }
      
      //Method of Executor Service
      void execute(final int jobId) {
          tasks.add(taskExecutor.submit(new Runnable() {
              void run() {
                  someProcessor.processJob(jobId);
              }
          }));
      }
      
      //Method of another Service
      @Transactional
      public void processJob(int jobId) {
          //this will work in separate thransaction since was executed in another Theread
          someDao.doWorkInExternalTransaction(jobId);
      }
      

      如果您确实需要控制外部事务 - 在 new Theread 中的单个外部事务中执行嵌套事务工作,然后等待 Thread 返回结果并在需要时抛出异常

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2012-07-21
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-06-25
        • 1970-01-01
        相关资源
        最近更新 更多