当前位置: 首页 > 知识库问答 >
问题:

为什么Spring Propagation=REQUIRED跨越嵌套逻辑事务

赫连黎昕
2023-03-14

似乎当具有嵌套传播的事务性spring方法调用另一个需要传播的事务性方法时,内部事务可以强制回滚外部逻辑事务。

例如,如果事务性方法Classa.MethodA(具有propagation=REQUIRED)调用事务性方法ClassB.MethodB(具有propagation=NESTED),MethodB(具有propagation=REQUIRED)又调用事务性方法ClassC.MethodC(具有propagation=REQUIRED),那么如果ClassC.MethodC发起回滚,则由Classa.MethodA开始的外部逻辑事务将在尝试提交时得到一个UnexpectedDrollBackException。

下面是上面讨论的代码示例:

public class ClassA {
  private ClassB classB;
  @Transactional(propagation = Propagation.REQUIRED)
  public void methodA() {
    try {
      classB.methodB();
     } catch (RuntimeException re) {
       // do nothing we don't want to fail, but alas we will get an UnexpectedRollbackException
     }
  }
}

public class ClassB {
  private ClassC classC;
  @Transactional(propagation = Propagation.NESTED)
  public void methodB() {
      classC.methodC();
  }
}

public class ClassC {
  @Transactional(propagation = Propagation.REQUIRED)
  public void methodC() {
      // If this method weren't transactional this would just return to the save point created by method B
      // I Want to just fail the NESTED transaction, but alas I'm going to fail everything
      throw new RuntimeException("Oh, woe is me!");
  }
}

共有1个答案

子车灿
2023-03-14

我不知道为什么会这样,但我找到了一个解决办法:

    public class ClassA {
        private ClassB classB;

        public void methodA() {
            try {
                classB.methodB();
            } catch (RuntimeException re) {
                // do nothing we don't want to fail, but alas we will get an UnexpectedRollbackException
            }
        }
    }

    public class ClassB {
        private ClassC classC;

        @Transactional(propagation = Propagation.NESTED)
        public void methodB() {
            classC.methodC();
        }
    }

    public class ClassC {
        private TransactionTemplate requiredTransaction = createRequiredTransactionTemplate();

        public void methodC() {
            if (TransactionSynchronizationManager.isActualTransactionActive()) {
                // We are already in transaction, do not wrap in transaction
                _methodC();
            } else {
                requiredTransaction.execute(cb -> {
                    _methodC();
                    return null;
                });
            }
        }

        private void _methodC() {
            throw new RuntimeException("Oh, woe is me!");
        }
    }

 类似资料:
  • 问题内容: JTA为什么不支持嵌套事务?是因为实现它们的复杂性(我对此表示怀疑)还是某些设计原则? 问题答案: (正如@Piotr Nowicki指出的那样,JTA 确实 允许嵌套事务,但这不是强制性的可选操作。) 为什么?这是无法确定地回答的问题之一,除非您是做出决定时“在房间里”的人之一。 将嵌套事务作为规范的一部分包括在内可能是固有的复杂性。或当时明显的复杂性;即他们不知道他们知道如何做一个

  • 问题内容: 根据文档ActiveRecord :: Transactions :: ClassMethods ,一个非新的嵌套事务将忽略回滚。从文档: 该被忽略,因为它是在一个子事务(或者更确切地说,它仍然是在父事务中,而不是自己的)。我不明白为什么两者都会忽略Rollback调用?我可以看到,由于子级’transaction’并不是真正的事务,它不会回滚’Nemu’块,但是为什么它不触发父级的回

  • 问题内容: 什么时候嵌套类可行?我看到的最常见的优点是“共享范围”(跨类使用变量)。 这是否比仅将嵌套类放入其自己的文件中并通过构造函数传递参数更具吸引力/最佳实践少? 问题答案: 使用嵌套类的原因有很多,其中包括: 这是一种对仅在一个地方使用的类进行 逻辑分组 的方法。 它增加了 封装 。 嵌套类可以导致更具 可读性和可维护性的代码 。 子级到父级的连接更为简单,因为它 直观地说明 了每个类的变

  • 这个问题不是关于优化代码的问题,而是一个关于短路逻辑运算符和普通逻辑运算符性能差异的技术问题,这可以归结为它们在硬件上如何执行。 是的,如果右操作数是昂贵的,那么尝试不求值它是有益的。但是对于像这样的简单条件,假设这些是原子变量,非短路逻辑运算符可能执行得更快。我说的对吗? 我假设短路逻辑运算符使用分支(没有官方来源,只是自己想的),因为如果不这样的话,你如何在按顺序执行指令的同时做出那些跳跃呢?