事务失效场景
Spring框架、配置问题
1、service没有交给spring管理;
2、没有在spring启用事务管理器
Aop代理问题
3、事务方法被final、static修饰;(如果一个方法被声明为 final
或者 static
,则该方法不能被子类重写,也就是说无法在该方法上进行动态代理,这会导致 Spring
无法生成事务代理对象来管理事务。)
4、同一个类中,方法内部调用;(事务是通过 Spring AOP
代理来实现的,而在同一个类中,一个方法调用另一个方法时,调用方法直接调用目标方法的代码,而不是通过代理类进行调用 。)
5、方法的访问权限不是public
底层数据库不支持
6、数据库的存储引擎不支持
@Transactional配置问题
7、配置错误的注解;
8、事务超时时间设置过短;(@Transactional(timeout = 1)
,timeout
属性被设置为 1
秒,这意味着如果事务在 1<span> </span>
秒内无法完成,则报事务超时了。)
9、使用了错误的事务传播机制;
10、rollbackFor属性配置错误
开发使用不当
11、事务注解被覆盖导致事务失效;
12、嵌套事务的坑;
13、事务多线程调用;
14、异常被捕获并处理了,没有重新抛出;
15、手动抛了别的异常
spring事务的实现方式原理 TransactionInterceptor
两种方式:
- 1、声明式事务,通过@Transactiional 注解实现
- 2、编程式事务,用户代码来控制事务的处理逻辑
事务的操作本来应该有数据库来进行控制,但是为了方便用户进行业务逻辑的操作,spring对事务功能做了扩展。一般使用声明式事务,当添加了注解之后,事务的自动提交功能就会关闭。
事务操作是AOP的一个核心体现。当方法添加了注解之后,spring会基于这个类生成一个代理对象,会将这个代理对象作为bean,当使用这个代理对象的方法时候,如果有事务处理,那么会先把事务的自动提交关闭,然后执行具体的业务逻辑,如果业务逻辑没有出现异常,那么代理逻辑会直接提交事务。如果出现任何异常情况,那么会直接进行回滚操作,当然用户也可以控制对哪些异常进行回滚操作。
spring 的事务传播机制
多个事务方法相互调用时,事务会有不同的传播特性,来保证事务的正常执行。
Required:默认的传播特效,如果当前没有事务,则新建一个事务,如果当前存在事务,则加入这个事务;
Supports:当前存在事务,则加入这个事务,如果当前没事务,则以非事务的方式执行;
Mandatory:当前存在事务,则加入当前事务,如果事务不存在,则抛出异常;
Required_New:创建一个新事务,如果存在当前事务,则挂起事务;
Not_Supported:以非事务方式执行,如果存在当前事务,则挂起事务;
Never:不使用事务,如果当前事务存在,则抛出异常;
Nested:如果当前事务存在,则在嵌套事务中执行,否则 Required 的操作一致
Nested 和Required_New 区别
Required_New新建一个事务,并且这个新事务与原有事务无关,而Nested则是在当前事务时会开启一个嵌套事务。
在Nested情况下,父事务回滚时,子事务也会回滚;
而Required_New情况下,原有事务回滚,不会影响新开启的事务。
Nested 和Required 区别
Required情况下,调用方存在事务时,则被调用方和调用方使用同一个事务,那么被调用方出现异常时,由于
共用同一个事务,所以无论是否catch异常,事务都会回滚,
而Nested情况下,被调用方发生异常时,调用方可以catch其异常,这样只有子事务回滚,父事务不会回滚。