当前配置
由于项目是 SSM 框架整合而成,MySQL 的事务配置如下:
1 | <!--数据源配置--> |
问题分析
在一个事务管理的接口,方法抛出了 NullPointerException
异常,但是有关数据库表的操作却没有回滚,伪代码片段如下:
1 | ... |
在 noticeLog
的插入过程中代码抛出了异常,但是 notice
却成功的插入到了数据库,相当于这个明明被事务管理的方法在遇到程序异常却没有回滚事务🤔。
查阅文档及资料,在 Spring 官方文档中有解释:
注意中间红框段落,翻译一下:
1 | In its default configuration, the Spring Framework’s transaction infrastructure code marks a transaction for rollback only in the case of runtime, unchecked exceptions. That is, when the thrown exception is an instance or subclass of RuntimeException. ( Error instances also, by default, result in a rollback). Checked exceptions that are thrown from a transactional method do not result in rollback in the default configuration. |
可以看到代码抛出 RuntimeException 的实例、子类或在默认情况下的 Error 才会导致回滚,但是,从事务方法抛出的已检查异常不会导致在默认配置中回滚。
所以代码中 try catch
捕获了异常,导致了事务无法回滚(⊙x⊙)。
解决方案
方案一
既然代码的异常被捕获后事务无法回滚,那么可以手动抛出 RuntimeException
的实例或子类:
1 | ... |
方案二
既然事务没有自动回滚,我们可以手动设置事务的回滚:
1 | ... |
再次调试运行后,事务正常回滚😊。