工作中经常会遇到事务的设置,有些地方还是不甚明了,就再了解了解,做了个笔记看看~

1 访问权限问题

private的方法,导致事务失效,spring要求被代理方法必须是public的。

不加权限的时候,方法默认的是??

2 方法用final修饰

spring事务底层使用了aop,也就是通过jdk动态代理或者cglib,帮我们生成了代理类,在代理类中实现的事务功能。

final的方法,在它的代理类中,无法重写该方法,无法添加事务功能。

3 方法内部调用

内部调用其实是通过this来调用的。如果要解决,就将这个Service本身进行注入

java事务失效场景及解决方案 java事务内部调用,事务失效_java事务失效场景及解决方案

4 未被spring管理

通常情况下,通过@Controller、@Service、@Component、@Repository等注解,可以自动实现bean实例化和依赖注入的功能。

如果忘记加这些注解,这个类就不会交给spring管理,就事务失效。

5 多线程调用

spring的事务是通过数据库连接来实现的。当前线程中保存了一个map<数据源,数据库连接>。

线程间的数据是隔离的,如果用多线程去调用一个方法的话,就会产生多份ThreadLocal,从而产生多个数据库连接,数据库也就不一样了。

同一个事务,是指同一个数据库连接,只有拥有同一个数据库连接,才能同时提交和回滚。

6 表不支持事务

引擎是myisam的就不支持事务。

7 未开启事务

spring是需要通过xml去配置的。springboot是默认开启事务的。

二 事务不会滚

1 错误的传播特性

@Transcational(propagation=传播特性),该参数指定事务的传播特性。Spring目前有7种。

java事务失效场景及解决方案 java事务内部调用,事务失效_回滚_02

目前能创建新事务的三种传播特性:Required、requires_new、nested

2 自己吞了异常

事务不会回滚,开发者在代码中手动try…catch了异常

java事务失效场景及解决方案 java事务内部调用,事务失效_java事务失效场景及解决方案_03

 

3 手动抛了别的异常

开发者没有手动捕获异常,但是抛得异常不正确,spring事务也不会回滚

java事务失效场景及解决方案 java事务内部调用,事务失效_spring_04

 如上:开发捕获异常,又手动抛出了异常:Exception,事务也不会回滚。spring事务,默认情况只回滚RuntimeException和Error,对于普通的Exception(非运行时异常)不会进行回滚。

4 自定义了回滚异常

java事务失效场景及解决方案 java事务内部调用,事务失效_java_05

spring通过rollbackFor参数,支持自定义回滚的异常。 

但是,设置的是BusinessException异常,但是报错不属于其,比如是:SqlException或其他的,事务也不会回滚。

虽然rollbackFor参数有默认值,但是阿里的规范手册中还是要求重新指定该参数。

rollbackFor默认值为:UncheckedException,包括了RuntimeException和Error,当知己使用@Transcational不指定rollbackFor时,Exception及其子类都不会出发回滚。

所以,一般建议写成:@Transcational(rollBackFor = Exception.class)

5 嵌套事务回滚多了

java事务失效场景及解决方案 java事务内部调用,事务失效_spring_06