【问题标题】:Spring transactions behaviourSpring事务行为
【发布时间】:2018-10-25 08:56:48
【问题描述】:

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

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

@Transactional
class A {

    @Autowired
    B b;

    @Autowired
    C c;

    void methodA() { // outer transaction, this should not be rollback but currently getting UnexpectedRollbackException
        b.methodB(() -> c.methodC());
    }
}

@Transactional(propagation = Propagation.NESTED)
class B {

    void methodB(Runnable action) { // inner nested transaction
        try{
            action.run();
        } catch (Exception e){
           // nothing
        }
    }
}

@Transactional
class C {
    void methodC() { // inner required transaction
        throw new RuntimeException();
    }
}

【问题讨论】:

  • 在看起来应该做的地方显示代码。
  • 我添加了示例代码

标签: java spring-transactions


【解决方案1】:

为什么不呢?传播NESTED 在当前事务中开始一个事务(如果存在),否则行为类似于REQUIRED。 javadocs 状态:

/**
 * Support a current transaction; create a new one if none exists.
 * Analogous to the EJB transaction attribute of the same name.
 * <p>This is typically the default setting of a transaction definition,
 * and typically defines a transaction synchronization scope.
 */
int PROPAGATION_REQUIRED = 0;

/**
 * Execute within a nested transaction if a current transaction exists,
 * behave like {@link #PROPAGATION_REQUIRED} else. There is no analogous
 * feature in EJB.
 * <p><b>NOTE:</b> Actual creation of a nested transaction will only work on
 * specific transaction managers. Out of the box, this only applies to the JDBC
 * {@link org.springframework.jdbc.datasource.DataSourceTransactionManager}
 * when working on a JDBC 3.0 driver. Some JTA providers might support
 * nested transactions as well.
 * @see org.springframework.jdbc.datasource.DataSourceTransactionManager
 */
int PROPAGATION_NESTED = 6;

值得注意的是 NESTED 只有在您的 JDBC 驱动程序支持保存点时才真正受支持。这意味着:

没有现有的交易
A(嵌套)
B(必填)

会有以下行为:

begin; -- called prior to A but in A's 
A.doSomething();
B.doSomethingThatCausesException()
rollback;

还有

现有交易
A(嵌套)
B(必填)

会有以下行为:

begin; -- called outside of the scope of A
savepoint A_savepoint
A.doSomething();
B.doSomethingThatCausesException();
rollback A_savepoint;

如果您的 JDBC 驱动程序支持嵌套事务。否则,它将表现得像第一个场景。另请参阅this 答案。

也就是说,我相信保存点带来的麻烦多于其价值,如果您以原子方式处理任何数据库操作,您将为自己省去很多潜在的麻烦。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-08-06
    • 1970-01-01
    • 1970-01-01
    • 2018-11-23
    • 2019-11-26
    • 1970-01-01
    • 2023-03-20
    • 2015-05-04
    相关资源
    最近更新 更多