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

时间:2015-10-22 09:22:37

标签: 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() {
        [...]
    }
}

修改

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

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

  

PROPAGATION_REQUIRED

     

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

     

但是,在内部事务范围设置的情况下   rollback-only标记,外部事务还没有决定   回滚本身,以及回滚(由内部静默触发)   事务范围)是意外的。相应的   此时抛出UnexpectedRollbackException。这是预料之中的   行为,以便永远不会误导交易的调用者   假设在确实没有执行提交时。所以,如果一个   内部事务(外部调用者不知道)默默地   将事务标记为仅回滚,外部调用者仍然调用   承诺。外部呼叫者需要接收   UnexpectedRollbackException清楚地表明回滚是   相反。

我的问题可以改写为:

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

3 个答案:

答案 0 :(得分:2)

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

事务逻辑范围包含事务属性,其边界确实是带注释的方法。

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

比照Spring TransactionInterceptor(评论是我的)

try {
        retVal = invocation.proceed();
}
catch (Throwable ex) {
        completeTransactionAfterThrowing(txInfo, ex);
        throw ex;
}

completeTransactionAfterThrowing():

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

AbstractPlatformTransactionManager.processRollback():

else if (status.isNewTransaction()) { //requiresnew
    doRollback(status);
}
else if (status.hasTransaction()) { //requiered
        [...]
        doSetRollbackOnly(status);
    }
}

答案 1 :(得分:0)

参见spring documentation的第16.5.7节。 即使内部方法在事务上下文中被调用时也使用REQUIRED进行注释,它将映射到相同的物理事务。

答案 2 :(得分:0)

在我对规范的理解中,我会在这个例子中说:

Class A {
    @Transactional(propagation = Propagation.REQUIRED,
        rollbackFor = { SomeException.class})
    void foo() {
        try {
           b.bar();
        } catch (OtherException e) {
           // the transaction is marked as rollback-only by the inner call as it thrown an OtherException
           // XXX --- or not if inner logical scope does not handle overridden property 'rollbackFor' ? ---
           // anyway, we avoid UnexpectedRollbackException by enforcing physical rollback to outter scope programmatically, by throwing :
           throw new SomeExeption(e);
        }
    }
}

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

所以我们可以将问题重新表述为:覆盖“rollbackFor”属性是由内部逻辑事务范围管理处理的吗?

顺便说一下,您使用的确切事务管理器类和版本是什么?