Spring-boot @Transactional 属性配置

@Transactional 属性配置

事务管理的目的

在出现异常的情况下,保证数据的一致性;数据提交操作回滚至异常发生前的状态

事务管理的方式:

SpringSpring Framework 提供对事务管理的抽象接口)
支持两种事务管理方式:
编程式事务管理

  • 使用 TransactionTemplatePlatformTransactionManager 实现
  • 编程式事务管理优势:可以控制事务的粒度,最细粒度到代码块级别;

声明式事务管理

  • 建立在 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 的本质决定的。在 protectedprivate 或者默认可见性的方法上使用 @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异常。这样是不是好记一些啦

posted @ 2020-08-29 20:16  Kotaku  阅读(845)  评论(0)    收藏  举报