Spring的@Transactional注解属性优先级/继承

9 浏览
0 Comments

Spring的@Transactional注解属性优先级/继承

在调用者方法本身已经是事务性的情况下,当传播行为设置为REQUIRED时,如果当前方法与包含它的事务属性不同,那么当前方法是否会覆盖它们(例如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() {
        [...]
    }
}

编辑

好的,我想避免显而易见的超出范围的答案,所以让我们清楚一点,我知道spring处理传播行为。

如果您不知道,请参阅文档的下面部分,我只想澄清上面我例子中第一部分的内容:

PROPAGATION_REQUIRED

当传播设置为PROPAGATION_REQUIRED时,对于每个应用设置该设置的方法,都将创建一个逻辑性事务范围。每个这样的逻辑性事务范围可以单独确定仅回滚状态,外部事务范围在逻辑上独立于内部事务范围。当然,在标准PROPAGATION_REQUIRED行为的情况下,所有这些范围都将映射到同一个物理事务。因此,在内部事务范围设置回滚唯一标记的情况下,外部事务尚未决定回滚自身,因此在内部事务范围默默触发回滚(您期望的方式),预计会发生回滚。在此时抛出相应的UnexpectedRollbackException异常。这是预期的行为,以便一个事务的调用者永远不会被误导以为已执行提交,而实际上并没有。因此,如果内部事务(外部调用者不知道其存在)默默将事务标记为仅回滚,那么外部调用者仍然会调用提交。外部调用者需要接收UnexpectedRollbackException以明确指示已执行回滚。

我的问题可以重新表述为:逻辑事务范围是否包含事务属性?

admin 更改状态以发布 2023年5月23日
0
0 Comments

根据我的理解,我会在这个例子中说:

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" 属性是否由内部逻辑事务范围管理处理?

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

0
0 Comments

因此,我设置了一个测试案例,简短的答案是是。

事务逻辑范围保存了事务属性,它的边界确实是被标注方法的边界。

因此,即使底层物理事务对两个方法都是相同的,逻辑属性对于每个方法是不同的,内部方法可以强制回滚外部方法的事务。
但如果这最后触发了提交,它将导致一个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);
    }
}

0