UnexpectedRollbackException---Spring事务管理简单分析

本文探讨了在Spring事务管理中遇到UnexpectedRollbackException的原因和解决策略。当Spring方法开启事务后,遇到异常,TransactionAspectSupport会处理并决定是否回滚。异常处理分为运行时异常和非运行时异常,前者默认回滚,后者则可能提交。如果异常发生在try...catch中,事务不会回滚。在commit时,如果内层事务异常但未向上抛出,外层事务仍会尝试commit,导致回滚并抛出UnexpectedRollbackException。避免这种异常的方法包括:正确处理内层事务异常,或使用独立事务。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

前言
最近项目中发生了一个事务异常:UnexpectedRollBackException,然后重温一下Spring的事务管理方面的知识

**

Spring事务捕获到异常以后的操作

**
首先是Spring的事务机制,当一个方法开启事务后,如果代码中发生了异常后,将会进入
TransactionAspectSupport中,代码大概如下
在这里插入图片描述
捕获异常后经过一些处理后交给TransactionAspectSupport.completeTransactionAfterThrowing方法处理,在图中2处判断该异常是否要进行回滚,默认情况下运行时异常回滚,非运行时异常不回滚直接提交,然后在图3处进行事务回滚
在这里插入图片描述
具体的事务回滚操作是在上图中所示代码进行的,首先判断该事务是否是一个新的事务,如果是一个新事务,则直接回滚,如果不是新的事务,则打上回滚标记,如下图所示
在这里插入图片描述
新事务是指新起的事务,如果是加入的别的方法的事务,则不为新事务
注意,如果异常发生在try…catch代码块中,将不会执行上述流程

如果该方法所起的不是外层事务,则捕获到的异常会向上抛给上层事务、

commit时候的操作

只有最外层事务在代码执行成功后(没有异常,或者异常被try…catch了,或者出现的异常为非运行时异常)才会commit
在这里插入图片描述
commit时主要执行的代码有这两个分支,当该事务完全执行成功,并且嵌套事务也完全成功时,会直接commit(图中2)
但是如果内层事务出现异常打上全局回滚标志以后,外层事务用try…catch捕获了内层事务抛出的异常,并在catch里没有继续向外抛出,在外层事务成功执行后commit时,就会走到上图中的1所示位置,这个时候就会回滚,并且抛出异常

 throw new UnexpectedRollbackException("Transaction rolled back because it has been marked as rollback-only");

避免UnexpectedRollbackException

由此可见发生UnexpectedRollbackException的主要原因就是,内存事务发生异常后打上了全局回滚标记,而外层事务通过try catch捕获以后进行了不处理的操作,所以要避免UnexpectedRollbackException的话,
1.外层事务调用内层事务时,不能忽略内层事务抛出的异常
2.把两个方法分别起两个事务,分别commit,同一事务嵌套内,一旦打上全局回滚标记,那么最外层事务commit时必然会进行回滚操作

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值