群友:事务中的异常不也抛出了,为什么没catch到而回滚?
上周,我们通过这篇文章《为什么catch了异常,但事务还是回滚了?》(https://blog.didispace.com/why-catch-exception-transaction-rollback/)来解释了,之前test4为什么会回滚的原因。
但还是收到了很多没有理解的反馈,主要是根据前文给出的线索去跟踪,是获得到了回滚的标示和异常,而让大家不理解的是,javax.validation.ConstraintViolationException
异常不是最后也向外抛出了,那么为什么test4里catch没有能够捕获到呢?
其实这个问题并不难解释,下面就通过这篇文章,做个小实验,帮助大家进一步理解catch不到异常的原因!
如果你还不了解这篇文章在讨论什么,建议先看之前的两篇:
- 《我来出个题:这个事务会不会回滚?》(https://blog.didispace.com/will-this-transcation-rollback/)
- 《为什么catch了异常,但事务还是回滚了?》(https://blog.didispace.com/why-catch-exception-transaction-rollback/)
动手尝试一下
由于@Transactional
注解的事务是通过切面来实现的,所以要通过源码去了解整个过程,可能还是会比较晕。
所以,这里教大家一个简单方法来理解这次test4的catch为什么没有捕获异常。
我们通过类似下面的方式,给test4多加一些日志信息和断点:
同时,记得也在上一篇说到的事务提交入口,也加上断点。
org.springframework.orm.jpa.JpaTransactionManager
然后尝试触发test4的执行,通过DEBUG,我们都可以观察到:
test4中我们加的断点,除了47行没进入,其他的一次性都执行完了。然后才进入了org.springframework.orm.jpa.JpaTransactionManager
的doCommit
方法。
所以,前文中我们跟踪的事务回滚所抛出的异常,其实是在test4中的try-catch块执行完之后才抛出的,所以内部的这个catch是无法捕获异常的,这里完全就是catch了个寂寞。
通过日志,我们也能观察到这样的执行顺序:
好了,通过这样来看,是不是要比之前有进一步的理解了呢?如果您还想更深入的了解事务的底层运行机制,一定要debug下源码,自己过一遍,理解会深刻哦!如果你没有得到跟我一样的结果,那更要找找原因,除了审题之外,再仔细跟踪下执行过程,这么做远比下面这样要得到更多收获哦~
如果你还有其他疑问,关注下方公众号,回复”加群“,加入我们的Spring技术交流群,参与交流与讨论,一起学习与进步!
如果您正在学习Spring Boot,我的免费教程一直在持续连载,欢迎关注我们长期连载的Spring Boot 2.x基础教程:http://blog.didispace.com/spring-boot-learning-2x/
往期推荐
Spring发布新成员:Spring GraphQL!高调出场的GraphQL能火起来了吗?
相关文章
- 【快问快答】事务异常或者instance abort时,如何估算事务rollback时间
- 【说站】python捕获多个异常的规则
- 【说站】python异常链是什么
- python错误和异常处理_python异常处理
- Python 异常处理
- 震惊!Linux调用C Main,居然使用的缺页异常
- 如果MySQL事务中发生了网络异常?
- 代码抛出异常后进行事务回滚的两种方式(Spring @Transactional注解)详解编程语言
- ForEach遍历ArrayList并删除其中元素时抛出异常:java.util.ConcurrentModificationException以及解决办法详解编程语言
- MySQL 异常处理:事务回滚(mysql异常回滚)
- 解决MSSQL中除数为0出现的异常(mssql 除数为0)
- Oracle异常导致事务回滚:一次损失双重承受!(oracle异常回滚)
- Java经验点滴:处理没有被捕获的异常
- asp.net错误:0x8007000B异常的解决方法