Spring Transaction事务
1. 目录
[TOC]
2. 介绍
当数据持久并非一次性入库的时候需要使用事务保证数据一致性。开启事务一般有两种模式:申明式事务和编程式事务
- 声明式事务:直接使用
@Transactional
注解开启事务,其意义为进入注解方法时自动开启事务,内部运行及调用都在事务中,运行完成此方法时主动关闭事务,其好处是程序自动控制并且关闭连接,程序开发时也非常方便。 - 编程式事务:在方法编写时手动开启事务,并且在用完之后需要手动关闭连接,否则连接不被释放。使用编程式事务大多在申明式事务不方便作用时,如在方法内部调用内部方法时,被调用的方法开启事务。
3. 原理
在spring中,@Transactional
注解用于开启自动事务。
开启后spring启动时会在bean的创建时主动扫描@Transactional
注解,并在initialBean
方法中通过动态代理创建TransactionManagement
类代理原类,从而保证加入容器的bean为代理之后的类。
在代码中注入bean的时候,实际上是注入的代理之后的bean,调用方法时首先调用代理类的代理方法,通过处理好代理方法后再执行原对象方法的方式加入事务管理,从而实现自动开启事务和关闭事务。
具体详细流程见源码分析
@Transactional
注解可以用于类或方法上,用于类上表示这个类的所有public方法都默认开启事务,用于方法上表示此类的此方法开启事务。
4. 使用
在spring中需要引入spring-tx
依赖包,使用spirngboot项目现在已经默认不需要添加注解@EnableTransactionManagement
即可开启。
在需要使用的类上加上@Transactional
注解即可,如下
1 |
|
5. 事务的特性
5.1. 传播特性
事务是可以嵌套的,即方法已经开启事务了,但是方法在调用其他方法时,其他方法也开启了事务,这时就出现了事务嵌套,需要指定相应的传播特性,@Transactional
中的propagation
参数即为指定对应的传播特性。
事务的7大传播特性枚举Propagation
如下:
1 | public enum Propagation { |
5.2. 隔离级别
事务除了具有传播特性,还有隔离级别,其也是对应数据库的隔离级别
事务的四大隔离级别枚举Isolation
如下:
1 | public enum Isolation { |
其特性具体可以参见数据库的隔离级别
5.3. 事务回滚
在@Transactional
中支持配置回滚策略,即发生异常时可以回滚数据,不提交,spring默认的回滚策略为发生RuntimeException
的时候。其配置属性为``robackFor`
因此,默认情况下抛出的异常只是Exception
异常而非RuntimeExcecption
时,回滚是不会生效的,也就是说会直接提交事务,提交修改的数据。针对此需要自己定义异常,如设置robackFor=Exception.class
或robackFor=Threable.class
6. 使用@Transactional
的注意事项
@Transactional
注解虽然方便,但使用不当也会导致事务不生效,使用时需要注意其失效场景
@Transactional
只能外部调用,不能类方法调用注解方法。原因是因为其动态代理原理,注入spring中的才是被代理过的类,只有通过容器的bean调用,才能走代理的相关逻辑,内部调用则是直接调用的内部方法,当然不会有任何效果。- 注意
@Transactional
的传播特性。如其特性为NOT_SUPPORTED或NEBVER,也不会生效 - 注意
@Transactional
的回滚策略。如使用默认回滚策略RuntimeExcecption
而又没有抛出运行时异常