上一节概述了如何在你的应用程序中以声明的方式为类(通常是服务层类)指定事务性设置的基本知识。本节描述了如何以简单的声明方式控制事务的回滚。
向 Spring 框架的事务基础架构表明事务工作将被回滚的推荐方法是,从 当前在事务上下文中执行的代码中抛出一个异常。Spring 框架的事务基础架构代码会在调用堆栈中捕获任何未处理的异常,并决定是否对事务进行回滚标记。
在其默认配置中,Spring 框架的事务基础架构代码只在 运行时未检查的异常 情况下标记事务进行回滚。也就是说,当抛出的异常是RuntimeException 的一个实例或子类时。(Error 实例默认也会导致回滚)。在默认配置中,从事务方法抛出的检查异常不会导致回滚。
你可以准确地配置哪些异常类型将事务标记为回滚,包括检查的异常。下面的 XML 片段演示了如何为一个被检查的、特定于应用程序的 Exception 类型配置回滚:
<tx:advice id="txAdvice" transaction-manager="txManager">
<tx:attributes>
<tx:method name="get*" read-only="true" rollback-for="NoProductInStockException"/>
<tx:method name="*"/>
</tx:attributes>
</tx:advice>
如果你不希望事务在抛出异常时被回滚,你也可以指定 「no rollback rules / 无回滚规则」。下面的例子告诉 Spring 框架的事务基础架构,即使面对未处理的 InstrumentNotFoundException,也要提交相关的事务:
<tx:advice id="txAdvice">
<tx:attributes>
<tx:method name="updateStock" no-rollback-for="InstrumentNotFoundException"/>
<tx:method name="*"/>
</tx:attributes>
</tx:advice>
当 Spring 框架的事务基础架构捕捉到一个异常,并咨询配置的回滚规则以确定是否将事务标记为回滚,最强的匹配规则获胜。因此,在下面的配置中,除了 InstrumentNotFoundException 之外的任何异常都会导致相关事务的回滚。
<tx:advice id="txAdvice">
<tx:attributes>
<tx:method name="*" rollback-for="Throwable" no-rollback-for="InstrumentNotFoundException"/>
</tx:attributes>
</tx:advice>
你也可以用编程方式表示需要回滚。虽然简单,但这一过程是相当具有侵入性的,它将你的代码与 Spring 框架的事务基础结构紧密地联系在一起。下面的例子展示了如何以编程方式指示所需的回滚:
public void resolvePosition() {
try {
// 一些业务逻辑...
} catch (NoProductInStockException ex) {
// 以编程方式触发回滚
TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
}
}
如果可能的话,我们强烈建议你使用声明式方法来回滚。如果你绝对需要的话,可以使用程序化回滚,但它的使用与实现一个干净的基于 POJO 的架构相冲突。