Spring-boot @Transactional 属性配置
@Transactional
属性配置
事务管理的目的
在出现异常的情况下,保证数据的一致性;数据提交操作回滚至异常发生前的状态
事务管理的方式:
Spring
(Spring Framework
提供对事务管理的抽象接口)
支持两种事务管理方式:
编程式事务管理
- 使用
TransactionTemplate
或PlatformTransactionManager
实现- 编程式事务管理优势:可以控制事务的粒度,最细粒度到代码块级别;
声明式事务管理
- 建立在
AOP
之上的。其本质是对方法前后进行拦截,然后在目标方法开始之前创建或者加入一个事务(此处取决于事务的传播行为),在执行完目标方法之后根据执行情况提交或者回滚事务(执行成功则提交,失败则进行实物的回滚)- 声明式实物管理优势:在方法外进行声明,事务控制的代码不会与业务逻辑代码混在一起,最细粒度到方法级别(解决方法:可以将需要进行事务管理的代码块独立为方法,通过方法间调用实现);符合
spring
倡导的非侵入式的开发方式,即业务处理逻辑代码与事务管理代码不放在一起
注解的属性列表
属性 | 类型 | 描述 |
---|---|---|
value | string | 可选的限定描述符,指定使用的事务管理器 |
propagation | enum: Propagation | 可选的事务传播行为设置 |
isolation | enum: Isolation | 可选的事务隔离级别设置 |
readOnly | boolean | 读写或只读事务,默认读写 |
timeout | int (单位是:秒) | 事务超时时间设置 |
rollbackFor | Class[],Class对象数组,必须继承自Throwable | 导致事务回滚的异常类数组 |
rollbackForClassName | String[],类名数组,必须继承自Throwable | 导致事务回滚的异常类名字数组 |
noRollbackFor | Class[],Class对象数组,必须继承自Throwable | 不会导致事务回滚的异常类数组 |
noRollbackForClassName | String[],类名数组,必须继承自Throwable | 不会导致事务回滚的异常类名字数组 |
enum: Propagation 、Isolation 枚举参数值介绍
enum : propagation 事务传播行为
介绍:如果在开始当前事务之前,一个事务上下文已经存在,此时有若干选项可以指定一个事务性方法的执行行为
TransactionDefinition.PROPAGATION_REQUIRED:如果当前存在事务,则加入该事务;如果当前没有事务,则创建一个新的事务。这是默认值。
TransactionDefinition.PROPAGATION_REQUIRES_NEW:创建一个新的事务,如果当前存在事务,则把当前事务挂起。
TransactionDefinition.PROPAGATION_SUPPORTS:如果当前存在事务,则加入该事务;如果当前没有事务,则以非事务的方式继续运行。
TransactionDefinition.PROPAGATION_NOT_SUPPORTED:以非事务方式运行,如果当前存在事务,则把当前事务挂起。
TransactionDefinition.PROPAGATION_NEVER:以非事务方式运行,如果当前存在事务,则抛出异常。
TransactionDefinition.PROPAGATION_MANDATORY:如果当前存在事务,则加入该事务;如果当前没有事务,则抛出异常。
TransactionDefinition.PROPAGATION_NESTED:如果当前存在事务,则创建一个事务作为当前事务的嵌套事务来运行;如果当前没有事务,则该取值等价于TransactionDefinition.PROPAGATION_REQUIRED。
enum : Isolation 事务的隔离级别
介绍:是指若干个并发的事务之间的隔离程度
Isolation.READ_UNCOMMITTED:读取未提交数据(会出现脏读, 不可重复读) 基本不使用
Isolation.READ_COMMITTED:读取已提交数据(会出现不可重复读和幻读)
Isolation.REPEATABLE_READ:可重复读(会出现幻读)
Isolation.SERIALIZABLE:串行化
属性说明
value
- 主要用来指定不同的事务管理器;主要用来满足在同一个系统中,存在不同的事务管理器。比如在Spring中,声明了两种事务管理器txManager1, txManager2.然后,用户可以根据这个参数来根据需要指定特定的txManager.
- 适用场景:在一个系统中,需要访问多个数据源或者多个数据库,则必然会配置多个事务管理器的
REQUIRED_NEW和NESTED两种不同的传播机制的区别
- REQUIRED_NEW:内部的事务独立运行,在各自的作用域中,可以独立的回滚或者提交;而外部的事务将不受内部事务的回滚状态影响
- ESTED的事务,基于单一的事务来管理,提供了多个保存点。这种多个保存点的机制允许内部事务的变更触发外部事务的回滚。而外部事务在混滚之后,仍能继续进行事务处理,即使部分操作已经被混滚。 由于这个设置基于JDBC的保存点,所以只能工作在
JDBC
的机制rollbackFor
- 让受检查异常回滚;即让本来不应该回滚的进行回滚操作
noRollbackFor
- 忽略非检查异常;即让本来应该回滚的不进行回滚操作
注意事项:
@Transactional
使用位置类上方
方法上方
Spring
建议不要在接口或者接口方法上使用该注解,因为这只有在使用基于接口的代理时它才会生效
当作用于类上时,该类的所有public
方法将都具有该类型的事务属性,同时,我们也可以在方法级别使用该标注来覆盖类级别的定义。
方法的访问权限为
public
@Transactional
注解应该只被应用到public
方法上,这是由Spring AOP
的本质决定的。在protected
、private
或者默认可见性的方法上使用@Transactional
注解,这将被忽略,也不会抛出任何异常
默认情况下,只有来自外部的方法调用才会被
AOP
代理捕获,也就是,类内部方法调用本类内部的其他方法并不会引起事务行为,即使被调用方法使用@Transactional
注解进行修饰
例如一:同一个类中方法,A方法未使用此标签,B使用了,C未使用,A 调用 B , B 调用 C ;则外部调用A之后,B的事务是不会起作用的
例如二:若是有上层(按照
Controller
层、Service
层、DAO
层的顺序)由Action
调用Service
直接调用,发生异常会发生回滚;若间接调用,Action
调用Service
中 的 A 方法,A无@Transactional
注解,B有,A调用B,B的注解无效
其他
- 事务方法的嵌套调用会产生事务传播
- spring 的事务管理是线程安全的
- 父类的声明的
@Transactional
会对子类的所有方法进行事务增强;子类覆盖重写父类方式可覆盖其@Transactional
中的声明配置 - 类名上方使用
@Transactional
,类中方法可通过属性配置覆盖类上的@Transactional
配置;比如:类上配置全局是可读写,可在某个方法上改为只读
解决Transactional注解不回滚
-
检查你方法是不是public的
-
你的异常类型是不是unchecked异常 如果我想check异常也想回滚怎么办,注解上面写明异常类型即可
@Transactional(rollbackFor=Exception.class)
-
默认情况下,Spring会对unchecked异常进行事务回滚;如果是checked异常则不回滚。 辣么什么是checked异常,什么是unchecked异常
-
java里面将派生于Error或者RuntimeException(比如空指针,1/0)的异常称为unchecked异常,其他继承自java.lang.Exception得异常统称为Checked Exception,如IOException、TimeoutException等
-
辣么再通俗一点:你写代码出现的空指针等异常,会被回滚,文件读写,网络出问题,spring就没法回滚了。然后我教大家怎么记这个,因为很多同学容易弄混,你写代码的时候有些IOException我们的编译器是能够检测到的,说以叫checked异常,你写代码的时候空指针等死检测不到的,所以叫unchecked异常。这样是不是好记一些啦