关键代码
关键类 RuleBasedTransactionAttribute
/*** Winning rule is the shallowest rule (that is, the closest in the* inheritance hierarchy to the exception). If no rule applies (-1),* return false.* @see TransactionAttribute#rollbackOn(java.lang.Throwable)*/@Overridepublic boolean rollbackOn(Throwable ex) {RollbackRuleAttribute winner = null;int deepest = Integer.MAX_VALUE;if (this.rollbackRules != null) {for (RollbackRuleAttribute rule : this.rollbackRules) {int depth = rule.getDepth(ex);if (depth >= 0 && depth < deepest) {deepest = depth;winner = rule;}}}// User superclass behavior (rollback on unchecked) if no rule matches.if (winner == null) {return super.rollbackOn(ex);}return !(winner instanceof NoRollbackRuleAttribute);}
父类的 rollbackOn 方法
/*** The default behavior is as with EJB: rollback on unchecked exception* ({@link RuntimeException}), assuming an unexpected outcome outside of any* business rules. Additionally, we also attempt to rollback on {@link Error} which* is clearly an unexpected outcome as well. By contrast, a checked exception is* considered a business exception and therefore a regular expected outcome of the* transactional business method, i.e. a kind of alternative return value which* still allows for regular completion of resource operations.* <p>This is largely consistent with TransactionTemplate's default behavior,* except that TransactionTemplate also rolls back on undeclared checked exceptions* (a corner case). For declarative transactions, we expect checked exceptions to be* intentionally declared as business exceptions, leading to a commit by default.* @see org.springframework.transaction.support.TransactionTemplate#execute*/@Overridepublic boolean rollbackOn(Throwable ex) {return (ex instanceof RuntimeException || ex instanceof Error);}
分析得出 事务的默认回滚是 RuntimeException 或者 Error
单元测试代码
@Testpublic void testDefaultRule() {RuleBasedTransactionAttribute rta = new RuleBasedTransactionAttribute();assertThat(rta.rollbackOn(new RuntimeException())).isTrue();assertThat(rta.rollbackOn(new MyRuntimeException(""))).isTrue();assertThat(rta.rollbackOn(new Exception())).isFalse();assertThat(rta.rollbackOn(new IOException())).isFalse();}
从单元测试中可以发现,默认情况下 Exception 和 IOException 是不会被回滚的
总结
很多同学包括我在初次接触事务的时候,经常会发现自己手动 throws了一个Exception事务没有回滚
