关键代码

关键类 RuleBasedTransactionAttribute

  1. /**
  2. * Winning rule is the shallowest rule (that is, the closest in the
  3. * inheritance hierarchy to the exception). If no rule applies (-1),
  4. * return false.
  5. * @see TransactionAttribute#rollbackOn(java.lang.Throwable)
  6. */
  7. @Override
  8. public boolean rollbackOn(Throwable ex) {
  9. RollbackRuleAttribute winner = null;
  10. int deepest = Integer.MAX_VALUE;
  11. if (this.rollbackRules != null) {
  12. for (RollbackRuleAttribute rule : this.rollbackRules) {
  13. int depth = rule.getDepth(ex);
  14. if (depth >= 0 && depth < deepest) {
  15. deepest = depth;
  16. winner = rule;
  17. }
  18. }
  19. }
  20. // User superclass behavior (rollback on unchecked) if no rule matches.
  21. if (winner == null) {
  22. return super.rollbackOn(ex);
  23. }
  24. return !(winner instanceof NoRollbackRuleAttribute);
  25. }

父类的 rollbackOn 方法

  1. /**
  2. * The default behavior is as with EJB: rollback on unchecked exception
  3. * ({@link RuntimeException}), assuming an unexpected outcome outside of any
  4. * business rules. Additionally, we also attempt to rollback on {@link Error} which
  5. * is clearly an unexpected outcome as well. By contrast, a checked exception is
  6. * considered a business exception and therefore a regular expected outcome of the
  7. * transactional business method, i.e. a kind of alternative return value which
  8. * still allows for regular completion of resource operations.
  9. * <p>This is largely consistent with TransactionTemplate's default behavior,
  10. * except that TransactionTemplate also rolls back on undeclared checked exceptions
  11. * (a corner case). For declarative transactions, we expect checked exceptions to be
  12. * intentionally declared as business exceptions, leading to a commit by default.
  13. * @see org.springframework.transaction.support.TransactionTemplate#execute
  14. */
  15. @Override
  16. public boolean rollbackOn(Throwable ex) {
  17. return (ex instanceof RuntimeException || ex instanceof Error);
  18. }

分析得出 事务的默认回滚是 RuntimeException 或者 Error

单元测试代码

  1. @Test
  2. public void testDefaultRule() {
  3. RuleBasedTransactionAttribute rta = new RuleBasedTransactionAttribute();
  4. assertThat(rta.rollbackOn(new RuntimeException())).isTrue();
  5. assertThat(rta.rollbackOn(new MyRuntimeException(""))).isTrue();
  6. assertThat(rta.rollbackOn(new Exception())).isFalse();
  7. assertThat(rta.rollbackOn(new IOException())).isFalse();
  8. }

从单元测试中可以发现,默认情况下 Exception 和 IOException 是不会被回滚的

总结

很多同学包括我在初次接触事务的时候,经常会发现自己手动 throws了一个Exception事务没有回滚

参考连接

spring-framework【GitHub】