Spring 事务异常 UnexpectedRollbackException

出现原因

Spring 框架的默认事务传播方式是 PROPAGATION_REQUIRED (内层事务加入外层事务中)

在内层事务因异常结束时, Spring 会把事务标记为 rollback-only. 这时如果外层事务 catch 捕捉了异常 e, 那么外层事务方法还会继续执行代码, 直到外层事务结束.

Spring 发现事务已经被标记为 rollback-only, 外层方法却正常执行成功, 这时 Spring 就会抛出 UnexpectedRollbackException

org.springframework.transaction.UnexpectedRollbackException:
	Transaction rolled back because it has been marked as rollback-only

解决方案

  1. 希望内层事务抛出异常时 中断程序执行, 在外层事务的 catch 代码块中继续抛出异常 e
  2. 如果希望程序正常执行完, 并且希望外层事务结束时 全部提交, 则在内层事务方法中将异常 e 捕获并处理
  3. 如果希望 内层事务回滚, 但不影响外层事务提交, 需要将内层事务的传播方式指定为 PROPAGATION_NESTED. (ps:PROPAGATION_NESTED 基于数据库 savepoint 实现的嵌套事务, 外层事务的提交和回滚能够控制嵌内层事务, 而内层事务报错时, 可以返回原始 savepoint, 外层事务可以继续提交.

Java 异常

在这里插入图片描述

  • 受检异常 checked exception vs 非受检异常 unchecked exception

  • (compile-time) Exceptions (checked) and RuntimeExceptions (unchecked)

  • common checked exceptions in Java are IOException, SQLException and ParseException

  • unchecked exception reflects some error inside the program logic like ArithmeticException

    • The RuntimeException class is the superclass of all unchecked exceptions
  • It’s a good practice to use exceptions in Java so that we can separate error-handling code from regular code

    • If a client can reasonably be expected to recover from an exception, make it a checked exception (compile)
    • If a client cannot do anything to recover from the exception, make it an unchecked exception (runtime)
  • exception vs error

    • You can, and probably should, recover from an exception
    • You can, but should not, recover from an error
  • 本质上 unchecked 和 runtime 是同义词, 但…
    在这里插入图片描述

  • 不要在方法签名中 throw RuntimeException 等 unchecked exception
    在这里插入图片描述

  • Spring 默认会对 RuntimeException 和 Error 异常进行回滚

  • Spring 没有对非运行时异常(检查时异常)进行处理,这是因为非运行时异常在编码时,是需要我们开发人员手动去进行 try/catch 进行处理的,也不允许抛出非运行时异常,比如 IOException,不然编译器编译都通不过,更别谈运行程序

  • 除了 IOException 等需要 try/catch 的异常, 还有一些不需要 try/catch 处理但是也不属于 RuntimeException 的异常, 比如: SQLException,尽管 JdbcTemplate 会将 SQLException 转为 BadSqlGrammarException (具体可以参考 translateException(String task, @Nullable String sql, SQLException ex) 方法)

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值