工作中经常会遇到事务的设置,有些地方还是不甚明了,就再了解了解,做了个笔记看看~
1 访问权限问题
private的方法,导致事务失效,spring要求被代理方法必须是public的。
不加权限的时候,方法默认的是??
2 方法用final修饰
spring事务底层使用了aop,也就是通过jdk动态代理或者cglib,帮我们生成了代理类,在代理类中实现的事务功能。
final的方法,在它的代理类中,无法重写该方法,无法添加事务功能。
3 方法内部调用
内部调用其实是通过this来调用的。如果要解决,就将这个Service本身进行注入
4 未被spring管理
通常情况下,通过@Controller、@Service、@Component、@Repository等注解,可以自动实现bean实例化和依赖注入的功能。
如果忘记加这些注解,这个类就不会交给spring管理,就事务失效。
5 多线程调用
spring的事务是通过数据库连接来实现的。当前线程中保存了一个map<数据源,数据库连接>。
线程间的数据是隔离的,如果用多线程去调用一个方法的话,就会产生多份ThreadLocal,从而产生多个数据库连接,数据库也就不一样了。
同一个事务,是指同一个数据库连接,只有拥有同一个数据库连接,才能同时提交和回滚。
6 表不支持事务
引擎是myisam的就不支持事务。
7 未开启事务
spring是需要通过xml去配置的。springboot是默认开启事务的。
二 事务不会滚
1 错误的传播特性
@Transcational(propagation=传播特性),该参数指定事务的传播特性。Spring目前有7种。
目前能创建新事务的三种传播特性:Required、requires_new、nested
2 自己吞了异常
事务不会回滚,开发者在代码中手动try…catch了异常
3 手动抛了别的异常
开发者没有手动捕获异常,但是抛得异常不正确,spring事务也不会回滚
如上:开发捕获异常,又手动抛出了异常:Exception,事务也不会回滚。spring事务,默认情况只回滚RuntimeException和Error,对于普通的Exception(非运行时异常)不会进行回滚。
4 自定义了回滚异常
spring通过rollbackFor参数,支持自定义回滚的异常。
但是,设置的是BusinessException异常,但是报错不属于其,比如是:SqlException或其他的,事务也不会回滚。
虽然rollbackFor参数有默认值,但是阿里的规范手册中还是要求重新指定该参数。
rollbackFor默认值为:UncheckedException,包括了RuntimeException和Error,当知己使用@Transcational不指定rollbackFor时,Exception及其子类都不会出发回滚。
所以,一般建议写成:@Transcational(rollBackFor = Exception.class)