这两天一直在研究一个东西,关于事务回滚的,因为我突然发现我们项目竟然不支持,不支持,但是我们整个事务的配置文件都是有的。
关于事务配置,我就不再多阐述了,可以参考这篇文章: 事务回滚配置
下面说我遇到的问题吧,就是所有的配置都完成了,但就是不起作用,抛出了RuntimeException就是不会滚,数据库操作该执行还是执行了。最后才想到会不会是数据库表引擎的问题,立马去看,果然,表引擎都是myisam,我的天,把引擎改一下,立马好了。
下面总结一下,在确认配置文件都配置好,所有工作都无误的情况下还是不支持事务时的几个检查方面:
使用@Transactional注解的回滚方式的检查方面:
1、看方法是否是public的,注解方式默认只在public修饰的方法上起作用,protected、private 或者 default 修饰的方法上使用@Transactional时不会报错,但是事务设置不起作用。
2、检查是不是同一个类中方法的调用。(比如同一个方法中存在A和B两个方法,A方法去调用B方法)
基于spring aop的配置回滚方式的检查方面:
1、配置文件中的aop相关配置,看expression配置的路径是否可以扫描到你的方法。
<aop:config>
<aop:pointcut id="transactionPointcut" expression="execution(* com.test.service.impl..*.*(..))" />
<aop:advisor pointcut-ref="transactionPointcut" advice-ref="transactionAdvice" />
</aop:config>
上面代码中我配置的是 扫描com.test.service.impl 包及其子包中的所有的方法。
顺便给出execution表达式常见的相关配置说明:
execution(public * *(..)) 任意的公共方法
execution(* set*(..)) 任何以set开头的方法
execution( * com.test.service.impl.*.*(..)) com.test.service.impl包下的任意方法
execution( * com.test.service.impl..*.*(..)) com.test.service.impl包及其子包下的任意方法
下面是以上两种配置方式都可能出现不回滚的检查方面:
1、数据库引擎要支持事务,如果是MySQL,注意表要使用支持事务的引擎,比如innodb,如果是myisam,事务配置是不起作用的。
2、看service是否进行了try...catch...但是没有在catch块中继续抛出异常。
以下代码进行了try...catch...将异常捕获了,所以spring没法识别你的异常,当然也不会进行回滚。
public void test () {
try{
insert(a);
delete(b)
} catch {
System.out.println("不会回滚!!!");
}
}
正解如下,进行了try...catch...之后再catch块中继续进行异常的抛出,这样就可以实现回滚。
public void test () {
try{
insert(a);
delete(b)
} catch {
throw new RuntimeException("操作失败!!!");
}
}
好了,到此结束,自己问题也解决了,希望简单的总结能帮到一个两个的同行!
此文为原创,转载请注明出处,谢谢!