JPA事务中的异常最后不也抛出了,为什么没被catch到而导致回滚?

Posted 程序猿DD

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了JPA事务中的异常最后不也抛出了,为什么没被catch到而导致回滚?相关的知识,希望对你有一定的参考价值。

上周,我们通过这篇文章《为什么catch了异常,但事务还是回滚了?》来解释了,之前test4为什么会回滚的原因。

但还是收到了很多没有理解的反馈,主要是根据前文给出的线索去跟踪,是获得到了回滚的标示和异常,而让大家不理解的是,javax.validation.ConstraintViolationException异常不是最后也向外抛出了,那么为什么test4里catch没有能够捕获到呢?

其实这个问题并不难解释,下面就通过这篇文章,做个小实验,帮助大家进一步理解大家的这个疑问!

如果你还不了解这篇文章在讨论什么,建议先看之前的两篇:

动手尝试一下

由于@Transactional注解的事务是通过切面来实现的,所以要通过源码去了解整个过程,可能还是不容易理解。

所以,这里教大家一个简单方法来理解这次test4的catch为什么没有捕获异常。

我们通过类似下面的方式,给test4多加一些日志信息和断点:

同时,记得也在上一篇说到的事务提交入口,也加上断点。

org.springframework.orm.jpa.JpaTransactionManager

然后尝试触发test4的执行,通过DEBUG,我们都可以观察到:

test4中我们加的断点,除了47行没进入,其他的一次性都执行完了。然后才进入了org.springframework.orm.jpa.JpaTransactionManagerdoCommit方法。

所以,前文中我们跟踪的事务回滚所抛出的异常,其实是在test4中的try-catch块执行完之后才抛出的,所以内部的这个catch是无法捕获异常的,这里完全就是catch了个寂寞。

通过日志,我们也能观察到这样的执行顺序:

好了,通过这样来看,是不是要比之前有进一步的理解了呢?如果您还想跟深入的了解事务的底层运行机制,一定要debug一下源码,自己过一遍,理解会深刻哦!如果你还有其他疑问,欢迎加入我们的Spring技术交流群,参与交流与讨论,一起学习与进步!如果您正在学习Spring Boot,我的免费教程一直在持续连载,欢迎关注Spring Boot 2.x基础教程

欢迎关注我的公众号:程序猿DD,分享其他地方看不到的知识与思考

以上是关于JPA事务中的异常最后不也抛出了,为什么没被catch到而导致回滚?的主要内容,如果未能解决你的问题,请参考以下文章

异常的执行流程

安卓中的 SAXParseException

测试期间的Spring Boot JPA事务 - 不会在插入时抛出密钥违例异常

spring事物回滚机制 (事务异常回滚,捕获异常不抛出就不会回滚)

JPA 中的 getSingleResult() 抛出异常

c# throw抛出上一个异常