Spring事务的实现原理:
- Spring事务底层是基于数据库事务和AOP机制的
- ⾸先对于使⽤了@Transactional注解的Bean,Spring会创建⼀个代理对象作为Bean
- 当调⽤代理对象的⽅法时,会先判断该⽅法上是否加了@Transactional注解
- 如果加了,那么则利⽤事务管理器创建⼀个数据库连接
- 并且修改数据库连接的autocommit属性为false,禁⽌此连接的⾃动提交。
- 然后执⾏当前⽅法,⽅法中会执⾏sql
- 执⾏完当前⽅法后,如果没有出现异常就直接提交事务
- 如果出现了异常,并且这个异常是需要回滚的就会回滚事务,否则仍然提交事务
Spring的事务可分为编程式事务和声明式事务
声明式事务存在的问题:
- 最小粒度也要作用在方法上,那么如果这个方法里有一些如RPC远程调用、消息发送、缓存更新、文件写入等操作。本地事务回滚了,这些操作也无法回滚。如果是编程式事务的话,业务代码中就会清清楚楚看到什么地方开启事务,什么地方提交,什么时候回滚。
- 相对而言声明式事务更容易失效
如以下几种场景就可能导致声明式事务失效:
-
@Transactional 应用在非 public 修饰的方法上
spring要求被代理方法必须是public的 -
方法用final修饰
spring的事务是根据aop来实现的切面增强,而spring的aop默认用的是cglib动态代理。cglib是基于父子类来进行动态代理的,会动态的帮我们生成代理类,而这个代理类又是继承于被代理类的。而如果父类的方法不是public的,子类就无法重写,也就不能进行增强了。 -
同一个类中方法调用,导致@Transactional失效
发⽣⾃调⽤,类⾥⾯使⽤this调⽤本类的⽅法(this通常省略),此时这个this对象不是代理类,⽽是对象本身 -
未被spring容器管理
就是这个bean没有被容器管理 -
@Transactional 注解属性 propagation 设置错误
目前只有这三种传播特性才会创建新事务:NESTED,REQUIRES_NEW,REQUIRED。 -
@Transactional 注解属性 rollbackFor 设置错误
rollbackFor是导致事务回滚的异常类数组,所有在这个数组当中的异常被catch了就会回滚,反之则不会回滚。所以如果手动抛了其他的异常,事务也不会回滚。 -
数据库引擎不支持事务
网友评论