说一下事情的原委吧,也希望后面遇到类似问题的朋友少走点弯路(希望大家能看一下,对你解决问题思路肯定有帮助):
自己之前是按照视频整合ssm框架,老师在配置好事务之后,并未进行测试,自己也是出于好奇就进行事务回滚测试,自己插入两条记录到数据库,第一条是正确信息,然后第二条是错误的,但是发现当报出异常后数据库信息未发生回滚,自己也是通过各方大佬是各种方法去做测试,依然没有一点效果(搞了一个下午,很崩溃),有时候被bug搞得比较晕的时候最应该做的就是什么也不做,休息一下,然后第二天还是依旧和bug继续做斗争,自己发现自己这些配置应该没错,毕竟大家都是这么配置的测试的都没问题,自己觉得应该换一种思路,是不是之前文件配置出现问题(之前没有想是因为跟老师配置的一样,没去质疑),不得不说idea这个工具确实是强大啊,能帮不少忙,大家看下我的配置要求(spring文件不对controller层进行管理,而springMVC只需要对controller进行管理)说到这里我想大家应该都知道,我的问题在哪里了吧,请看图:
这里是applicationContext.xml文件的注解扫描配置,idea点击左边那个查看就能看到你现在配置情况下能扫描到的类了,这里完全符合我的预期目的。
附上代码:
<!--开启注解扫描,处理service层和dao层,controller不需要spring去处理-->
<context:component-scan base-package="snack">
<!--配置那些注解不扫描-->
<context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
</context:component-scan>
然后再看下spingMVC的配置文件图:
这里很明显它能够扫描到我现在所有类的注解,而我值仅仅需要它扫描studentController这个类(因为之前一直以为include是选择一个报下符合条件的类,其他都排除,而exclude则是除了..在外其他都符合,这里看来include好像跟我理解不一样,稍后我会再去了解)。
标签介绍:https://blog.csdn.net/chlei_/article/details/100576908
代码也附上:
<!--开启扫描注解,只扫描Controller注解-->
<context:component-scan base-package="snack">
<context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
</context:component-scan>
最后自己修改成精确到那个包(cotroller):
<!--开启扫描注解,只扫描Controller注解-->
<context:component-scan base-package="snack.controller">
<context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
</context:component-scan>
总结一下解决此类问题的思路:
先要明确自己配置的文件管理范围没有重复,就是像我这里,最好的方式就是我说的,idea查看你配置后的能扫描到的文件注解范围,当然如果你没用idea,我的另一种方法就是建议你换成idea,再者就是你的注释必须是在service实现层(反正我是,你要是调皮谁你便),然后事务问题再不能回滚那就是事务本身的使用问题了,这就是要明确bug出在哪里,这很重要,后面自己也是把事务的很多别人遇到的bug测试了一遍(一下午也算有点收获,就是这些了)。
下面总结一下:
首先要明确,spring事务默认回滚的就是RuntimeException这个异常类及其子类,我很好奇为什么连Exception也是默认不能回滚的(可能父类不能回滚,说白了就是自己包括自己儿子可以,自己父辈以上不管,有点不孝的嫌疑,但是毕竟是外国人开发的,原谅它),所以你需要它回滚,那么解决方法下面也是有几种:
一、就是不要进行try catch,如下(我已经测试过了,没问题):
二、如果你非要try catch进行处理,那么下面也是有两个解决方案的:
1.因为默认进行抛RuntimeException,那么我们就给他抛这个异常不就好了(这里也测了):
try {
//这里是前端传入的
studentDao.saveStudent(student);
//这里是测试异常的,我只输入一个属性,名字属性会报空异常
Student student1 = new Student();
student1.setSex("女");
studentDao.saveStudent(student1);
} catch (Exception e) {
e.printStackTrace();
throw new RuntimeException();
}
2.手动提交回滚操作(这里会测的):
@Transactional(rollbackFor = Exception.class)
public void saveStudent(Student student) {
try {
//这里是前端传入的
studentDao.saveStudent(student);
//这里是测试异常的,我只输入一个属性,名字属性会报空异常
Student student1 = new Student();
student1.setSex("女");
studentDao.saveStudent(student1);
} catch (Exception e) {
e.printStackTrace();
//手动提交事务回滚
TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
}
}
这里提示一下:有很多人因为没有加rollbackFor = Exception.class导致不能回滚,那就是因为默认是RuntimeException,不能进 行提交事务,你的rollbackFor属性就是定义碰到什么异常给你回滚,这里定义exception,估计绝大部分都没什 么问题了。
最后希望对需要的人能够有帮助,祝您早日战胜bug....