天天看点

ssm框架事务回滚问题(艰辛总结)

自己之前是按照视频整合ssm框架,老师在配置好事务之后,并未进行测试,自己也是出于好奇就进行事务回滚测试,自己插入两条记录到数据库,第一条是正确信息,然后第二条是错误的,但是发现当报出异常后数据库信息未发生回滚,自己也是通过各方大佬是各种方法去做测试,依然没有一点效果(搞了一个下午,很崩溃),有时候被bug搞得比较晕的时候最应该做的就是什么也不做,休息一下,然后第二天还是依旧和bug继续做斗争,自己发现自己这些配置应该没错,毕竟大家都是这么配置的测试的都没问题,自己觉得应该换一种思路,是不是之前文件配置出现问题(之前没有想是因为跟老师配置的一样,没去质疑),不得不说idea这个工具确实是强大啊,能帮不少忙,大家看下我的配置要求(spring文件不对controller层进行管理,而springMVC只需要对controller进行管理)说到这里我想大家应该都知道,我的问题在哪里了吧,请看图:

ssm框架事务回滚问题(艰辛总结)

这里是applicationContext.xml文件的注解扫描配置,idea点击左边那个查看就能看到你现在配置情况下能扫描到的类了,这里完全符合我的预期目的。

附上代码:

  1. <!--开启注解扫描,处理service层和dao层,controller不需要spring去处理-->
  2. <context:component-scan base-package="snack">
  3. <!--配置那些注解不扫描-->
  4. <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
  5. </context:component-scan>

然后再看下spingMVC的配置文件图:

ssm框架事务回滚问题(艰辛总结)

这里很明显它能够扫描到我现在所有类的注解,而我值仅仅需要它扫描studentController这个类(因为之前一直以为include是选择一个报下符合条件的类,其他都排除,而exclude则是除了..在外其他都符合,这里看来include好像跟我理解不一样,稍后我会再去了解)。

标签介绍:https://blog.csdn.net/chlei_/article/details/100576908

代码也附上:

  1. <!--开启扫描注解,只扫描Controller注解-->
  2. <context:component-scan base-package="snack">
  3. <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
  4. </context:component-scan>

最后自己修改成精确到那个包(cotroller):

  1. <!--开启扫描注解,只扫描Controller注解-->
  2. <context:component-scan base-package="snack.controller">
  3. <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
  4. </context:component-scan>

总结一下解决此类问题的思路:

先要明确自己配置的文件管理范围没有重复,就是像我这里,最好的方式就是我说的,idea查看你配置后的能扫描到的文件注解范围,当然如果你没用idea,我的另一种方法就是建议你换成idea,再者就是你的注释必须是在service实现层(反正我是,你要是调皮谁你便),然后事务问题再不能回滚那就是事务本身的使用问题了,这就是要明确bug出在哪里,这很重要,后面自己也是把事务的很多别人遇到的bug测试了一遍(一下午也算有点收获,就是这些了)。

下面总结一下:

首先要明确,spring事务默认回滚的就是RuntimeException这个异常类及其子类,我很好奇为什么连Exception也是默认不能回滚的(可能父类不能回滚,说白了就是自己包括自己儿子可以,自己父辈以上不管,有点不孝的嫌疑,但是毕竟是外国人开发的,原谅它),所以你需要它回滚,那么解决方法下面也是有几种:

一、就是不要进行try catch,如下(我已经测试过了,没问题):

ssm框架事务回滚问题(艰辛总结)

二、如果你非要try catch进行处理,那么下面也是有两个解决方案的:

1.因为默认进行抛RuntimeException,那么我们就给他抛这个异常不就好了(这里也测了):

  1. try {
  2. //这里是前端传入的
  3. studentDao.saveStudent(student);
  4. //这里是测试异常的,我只输入一个属性,名字属性会报空异常
  5. Student student1 = new Student();
  6. student1.setSex( "女");
  7. studentDao.saveStudent(student1);
  8. } catch ( Exception e) {
  9. e.printStackTrace();
  10. throw new RuntimeException();
  11. }

2.手动提交回滚操作(这里会测的):

  1. @Transactional(rollbackFor = Exception.class)
  2. public void saveStudent(Student student) {
  3. try {
  4. //这里是前端传入的
  5. studentDao.saveStudent(student);
  6. //这里是测试异常的,我只输入一个属性,名字属性会报空异常
  7. Student student1 = new Student();
  8. student1.setSex( "女");
  9. studentDao.saveStudent(student1);
  10. } catch (Exception e) {
  11. e.printStackTrace();
  12. //手动提交事务回滚
  13. TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
  14. }
  15. }

这里提示一下:有很多人因为没有加rollbackFor = Exception.class导致不能回滚,那就是因为默认是RuntimeException,不能进                           行提交事务,你的rollbackFor属性就是定义碰到什么异常给你回滚,这里定义exception,估计绝大部分都没什                             么问题了。

最后希望对需要的人能够有帮助,祝您早日战胜bug....

继续阅读