Java 为什么Spring Propagation=需要跨嵌套逻辑事务
似乎当一个具有嵌套传播的事务性spring方法调用另一个具有所需传播的事务性方法时,内部事务可以强制回滚外部逻辑事务 例如,如果事务性方法ClassA.methodA(其传播=必需)调用事务性方法ClassB.methodB(其传播=嵌套),后者反过来调用事务性方法ClassC.methodC(其传播=必需),则如果ClassC.methodC启动回滚,然后,由ClassA.methodA开始的外部逻辑事务如果试图提交,将得到一个意外的回滚异常 如果C失败,B拥有的逻辑嵌套事务应该被强制回滚,这是有意义的,但是C拥有的逻辑事务,并且从B内部调用的逻辑事务本身不会影响A的逻辑事务,应该能够影响A的逻辑事务,这是没有意义的。这似乎造成了methodA不能将methodB视为黑盒的情况,因为从表面上看,方法B似乎不能影响a的事务,但取决于它内部的行为,它可能会违反嵌套事务边界。为什么这是可能的?为什么spring选择以这种方式实现它 下面是上面讨论的代码示例:Java 为什么Spring Propagation=需要跨嵌套逻辑事务,java,spring,transactions,Java,Spring,Transactions,似乎当一个具有嵌套传播的事务性spring方法调用另一个具有所需传播的事务性方法时,内部事务可以强制回滚外部逻辑事务 例如,如果事务性方法ClassA.methodA(其传播=必需)调用事务性方法ClassB.methodB(其传播=嵌套),后者反过来调用事务性方法ClassC.methodC(其传播=必需),则如果ClassC.methodC启动回滚,然后,由ClassA.methodA开始的外部逻辑事务如果试图提交,将得到一个意外的回滚异常 如果C失败,B拥有的逻辑嵌套事务应该被强制回滚,这
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!");
}
}
我不知道为什么会这样,但我找到了一个解决办法:
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!");
}
}
这是4岁。。你找到解决办法了吗?