Spring @Transactional Annotation属性优先级/继承

Gab*_*ica 7 java spring transactions spring-transactions

REQUIRED传播的情况下,当调用方法本身是transactionnal时,如果它们不同,当前方法是否会覆盖封闭的事务属性(例如rollbackFor)?

插图:

Class A {
    @Transactional(propagation = Propagation.REQUIRED,
        rollbackFor = { SomeException.class})
    void foo() {
        try {
           b.bar();
        } catch (OtherException e) {
           // is the transaction marked as rollback-only at this point ?
        }
    }
}

Class B {
    @Transactional(propagation = Propagation.REQUIRED,
        rollbackFor = { OtherException.class})
    void bar() {
        [...]
    }
}
Run Code Online (Sandbox Code Playgroud)

编辑:

好吧,我想避免琐碎的范围答案,所以我们要清楚,我知道弹簧传播处理.

如果你不是,下面是文档的相关部分,我只想澄清关于我上面例子的第一部分:

PROPAGATION_REQUIRED

当传播设置为PROPAGATION_REQUIRED时,将为应用该设置的每个方法创建逻辑事务范围.每个这样的逻辑事务范围可以单独确定仅回滚状态,外部事务范围在逻辑上独立于内部事务范围.当然,在标准PROPAGATION_REQUIRED行为的情况下,所有这些范围将映射到同一物理事务.因此,内部事务范围中的仅回滚标记集确实会影响外部事务实际提交的机会(正如您所期望的那样).

但是,在内部事务作用域设置仅回滚标记的情况下,外部事务尚未决定回滚本身,因此回滚(由内部事务作用域静默触发)是意外的.此时抛出相应的UnexpectedRollbackException.这是预期的行为,因此事务的调用者永远不会被误导,假设在实际上没有执行提交.因此,如果内部事务(外部调用者不知道)以静默方式将事务标记为仅回滚,则外部调用者仍会调用commit.外部调用者需要接收UnexpectedRollbackException以清楚地指示已执行回滚.

我的问题可以改写为:

逻辑事务范围是否包含事务属性?

Gab*_*ica 3

所以,我设置了一个测试用例,简短的答案是肯定的。

事务逻辑范围保存事务属性,其边界实际上是带注释的方法边界。

因此,即使两种方法的底层物理事务相同,逻辑属性也适用于每个方法,并且内部方法可以强制回滚外部方法事务。如果最后触发提交,则会导致 UnexpectedRollbackException。

参见 Spring TransactionInterceptor(评论是我的)

try {
        retVal = invocation.proceed();
}
catch (Throwable ex) {
        completeTransactionAfterThrowing(txInfo, ex);
        throw ex;
}
Run Code Online (Sandbox Code Playgroud)

CompleteTransactionAfterThrowing() :

// txinfo is proper to the invocation target method
if (txInfo.transactionAttribute.rollbackOn(ex)) {
            try {
                txInfo.getTransactionManager().rollback(txInfo.getTransactionStatus());
            }
Run Code Online (Sandbox Code Playgroud)

AbstractPlatformTransactionManager.processRollback() :

else if (status.isNewTransaction()) { //requiresnew
    doRollback(status);
}
else if (status.hasTransaction()) { //requiered
        [...]
        doSetRollbackOnly(status);
    }
}
Run Code Online (Sandbox Code Playgroud)