使用spring声明式事务失效之第二弹
程序员文章站
2022-07-14 17:11:56
...
最近又在搭一个新的开发框架,并把阿里的dubbo服务化框架集成了进来,集成ok后并配置了声明式事务,但测试结果是不会回滚。
测试代码如下
事务配置和之前的项目配置方法一样,执行junit测试并抛出异常,查询数据库,却查到新加了一条数据 ,事务配置如下
仔细看了配置,并排除了因springmvc与spring使用注解扫描同一个包导致事务失效原因后也没发现什么问题,之后不停的进行尝试,并进行修改代码,
依然没有回滚,后看到网上有说spring声明式事务只捕获到RuntimeException异常才能回滚事务随修改为throw new RuntimeException();事务果然能正常回滚,但为什么不添加这行代码
到此问题原因都知道了,那如何修改呢,有人说都抛出RuntimeException不就ok了吗,或许是一种方法,我的方法是修改配置,修改为:
只要出现Exception就进行回滚。
这个问题查来查去最后只加了一个配置就解决了,解决过程有点曲折,从侧面也反映出对spring的事务管理这方面知识缺乏一定的深度及全面性。
测试代码如下
public boolean addUser(SysUser user) throws Exception { dubboTestDao.addUser(user); SysUser sysUser = new SysUser(); dubboTestDao.addUser(sysUser); return true; }
事务配置和之前的项目配置方法一样,执行junit测试并抛出异常,查询数据库,却查到新加了一条数据 ,事务配置如下
<!--声明式事务控制 --> <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource"/> </bean> <!-- 指定事务切入点 凡是实现了以cn.frame打头的包及其子包里以Service结尾接口中的所有方法需要由事务进行控制--> <aop:config> <aop:pointcut id="serviceOperation" expression="execution(* com..*Srv.*(..))" /> <aop:advisor pointcut-ref="serviceOperation" advice-ref="txAdvice" /> </aop:config> <tx:advice id="txAdvice" transaction-manager="transactionManager"> <tx:attributes> <!-- 读取数据方法,一般采用只读事务--> <tx:method name="get*" read-only="true"/> <tx:method name="query*" read-only="true"/> <tx:method name="find*" read-only="true"/> <tx:method name="load*" read-only="true"/> <!--等其它增删改数据操作,当产生Exception时都进行回滚 --> <tx:method name="*" propagation="REQUIRED" /> </tx:attributes> </tx:advice>
仔细看了配置,并排除了因springmvc与spring使用注解扫描同一个包导致事务失效原因后也没发现什么问题,之后不停的进行尝试,并进行修改代码,
public boolean addUser(SysUser user) throws Exception { dubboTestDao.addUser(user); SysUser sysUser = new SysUser(); dubboTestDao.addUser(sysUser); if(1==1)throw new Exception(); return true; }
依然没有回滚,后看到网上有说spring声明式事务只捕获到RuntimeException异常才能回滚事务随修改为throw new RuntimeException();事务果然能正常回滚,但为什么不添加这行代码
if(1==1)throw new Exception();就不会回滚呢,同样都是抛出异常,唯一不一样的也就是炮出的异常类型不一样,项目中用的ibatis,由于是新new的一个对象没有设置属性就进行insert,肯定会抛异常,查看异常类型是
com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException并查看了该类的父类一层一层往上查,该类最上面继承的是"SqlException>Exception",并没有继承RuntimeException,到此也就明白了问题所在,由于数据的问题抛出的异常类型是没有继承RuntimeException,因此spring也就不能正确的进行捕获并处理事务进行回滚, 这个问题看来之前没注意啊,之前给的感觉是任何异常都可以进行回滚,之前的测试类可能正好抛出的是RuntimeException类异常而没发现问题所在。
到此问题原因都知道了,那如何修改呢,有人说都抛出RuntimeException不就ok了吗,或许是一种方法,我的方法是修改配置,修改为:
<tx:method name="*" propagation="REQUIRED" rollback-for="Exception"/>
只要出现Exception就进行回滚。
这个问题查来查去最后只加了一个配置就解决了,解决过程有点曲折,从侧面也反映出对spring的事务管理这方面知识缺乏一定的深度及全面性。
推荐阅读
-
Spring实战之使用XML方式管理声明式事务操作示例
-
Spring实战之使用TransactionProxyFactoryBean实现声明式事务操作示例
-
使用spring声明式事务失效之第二弹
-
使用spring声明式事务失效之第二弹
-
使用spring+springMVC 组合开发,声明式事务失效
-
使用spring+springMVC 组合开发,声明式事务失效
-
Spring 2.5整合iBATIS 2.3并使用Spring的声明式事务管理
-
Spring 2.5整合iBATIS 2.3并使用Spring的声明式事务管理
-
Spring事务管理实现方式之编程式事务与声明式事务
-
使用Spring的声明式事务----AOP方式