Spring事务行为

9 浏览
0 Comments

Spring事务行为

当一个具有NESTED传播属性的事务spring方法调用另一个具有REQUIRED传播属性的事务方法时,内部事务可以强制回滚外部逻辑事务。有人可以确认吗?

我想处理RuntimeException并且不回滚外部事务,例如:

@Transactional
class A {
    @Autowired
    B b;
    @Autowired
    C c;
    void methodA() { // 外部事务,这不应该回滚,但当前出现UnexpectedRollbackException
        b.methodB(() -> c.methodC());
    }
}
@Transactional(propagation = Propagation.NESTED)
class B {
    void methodB(Runnable action) { // 内部嵌套事务
        try{
            action.run();
        } catch (Exception e){
           // 什么都不做
        }
    }
}
@Transactional
class C {
    void methodC() { // 内部必需的事务
        throw new RuntimeException();
    }
}

0
0 Comments

Spring事务的行为是如何的?为什么会出现这种问题?问题的解决方法是什么?

在Spring框架中,事务的传播行为有多种选项,其中包括NESTED和REQUIRED。NESTED会在当前事务存在时在当前事务内创建一个新的子事务,否则会像REQUIRED一样创建一个新的事务。然而,需要注意的是,NESTED只有在JDBC驱动程序支持保存点(savepoints)时才会真正被支持。

如果没有已经存在的事务,那么在NESTED的情况下,事务的行为如下:

开始事务(begin)

执行A.doSomething()

执行B.doSomethingThatCausesException()

回滚事务(rollback)

如果已经存在一个事务,那么在NESTED的情况下,事务的行为如下:

开始事务(begin)- 在A的作用域之外被调用

保存点A_savepoint

执行A.doSomething()

执行B.doSomethingThatCausesException()

回滚到保存点A_savepoint(rollback A_savepoint)

需要注意的是,以上行为仅在JDBC驱动程序支持嵌套事务时才会发生,否则它将像第一种情况一样行为。因此,如果你的JDBC驱动程序不支持嵌套事务,那么在使用NESTED传播行为时,它将像REQUIRED一样行为。

我认为保存点会带来更多的麻烦,如果你将数据库操作作为一个原子操作来处理,那么你将避免许多潜在的麻烦。

0