最近又在搭一个新的开发框架,并把阿里的dubbo服务化框架集成了进来,集成ok后并配置了声明式事务,但测试结果是不会回滚。
测试代码如下
事务配置和之前的项目配置方法一样,执行junit测试并抛出异常,查询数据库,却查到新加了一条数据 :cry: ,事务配置如下
仔细看了配置,并排除了因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测试并抛出异常,查询数据库,却查到新加了一条数据 :cry: ,事务配置如下
<!--声明式事务控制 -->
<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也就不能正确的进行捕获并处理事务进行回滚, :cry: 这个问题看来之前没注意啊,之前给的感觉是任何异常都可以进行回滚,之前的测试类可能正好抛出的是RuntimeException类异常而没发现问题所在。
到此问题原因都知道了,那如何修改呢,有人说都抛出RuntimeException不就ok了吗,或许是一种方法,我的方法是修改配置,修改为:
<tx:method name="*" propagation="REQUIRED" rollback-for="Exception"/>
只要出现Exception就进行回滚。
这个问题查来查去最后只加了一个配置就解决了,解决过程有点曲折,从侧面也反映出对spring的事务管理这方面知识缺乏一定的深度及全面性。