插图:
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
When the propagation setting is PROPAGATION_required,a logical
transaction scope is created for each method upon which the setting is
applied. Each such logical transaction scope can determine
rollback-only status individually,with an outer transaction scope
being logically independent from the inner transaction scope. Of
course,in case of standard PROPAGATION_required behavior,all these
scopes will be mapped to the same physical transaction. So a
rollback-only marker set in the inner transaction scope does affect
the outer transaction’s chance to actually commit (as you would expect
it to).However,in the case where an inner transaction scope sets the
rollback-only marker,the outer transaction has not decided on the
rollback itself,and so the rollback (silently triggered by the inner
transaction scope) is unexpected. A corresponding
UnexpectedRollbackException is thrown at that point. This is expected
behavior so that the caller of a transaction can never be misled to
assume that a commit was performed when it really was not. So if an
inner transaction (of which the outer caller is not aware) silently
marks a transaction as rollback-only,the outer caller still calls
commit. The outer caller needs to receive an
UnexpectedRollbackException to indicate clearly that a rollback was
performed instead.
我的问题可以改写为:
逻辑事务范围是否包含事务属性?
解决方法
因此,即使两个方法的底层物理事务都相同,逻辑属性也适用于每个方法,而内部方法可以强制回滚外部方法事务.
如果最后一次触发提交,则会导致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); } }