Spring 事务和事务传播机制

事务

事务指逻辑上的一组操作,组成这组操作的各个单元,要么全部成功,要么全部失败

为什么要用事务

举个例子:就好比充值点券这个操作,可以分为两步操作,付钱和点券到账,当你完成付钱这个操作后,结果点券没有到账,这显然是不合理的,此时就可以用事务进行解决这个问题,这一组操作要么一起成功,要么一起失败

Spring 中事务的实现

Spring编程式事务(手动写代码操作事务)

Spring ⼿动操作事务和MySQL 操作事务类似,它也是有 3 个重要操作步骤:

  1. 开启事务
  2. 提交事务
  3. 回滚事务

SpringBoot 内置了两个对象,DataSourceTransactionManager(数据源事务管理器)⽤来获取事务、提交或回滚事务的,⽽ TransactionDefinition 是事务的属性,在获取事务的时候需要将 TransactionDefinition 传递进去从⽽获得⼀个事务 TransactionStatus,代码实现如下:

@RestController
@RequestMapping("/art")
public class ArticleInfoController {
    @Autowired
    private ArticleInfoService articleInfoService;

    @Autowired
    private DataSourceTransactionManager dataSourceTransactionManager;

    @Autowired
    private TransactionDefinition transactionDefinition;


    @RequestMapping("/add")
    public int add(){
        //1.获取事务
        TransactionStatus transactionStatus= dataSourceTransactionManager.getTransaction(transactionDefinition);
        //业务代码插入文章
        int ret = articleInfoService.add();
        //2. 提交事务
        dataSourceTransactionManager.commit(transactionStatus);
        //回滚事务
        // dataSourceTransactionManager.rollback(transactionStatus);
        return ret ;
    }
}

Spring声明式事务(利用注解自动开启和提交事务)

相较于上面编程式事务,声明式事务显得非常便捷和简单,只需要在需要的方法上添加@Transactional 注解即可实现,不需要手段开启事务和提交事务,进入方法时自动进行开启事务,方法执行完后,会自动提交事务,当方法执行途中如果出现异常且没有处理会自动进行回滚

代码实现如下:

  @Transactional//只需要加上这一个注解即可
    @RequestMapping("/add1")
    public int add1(){
        int ret = articleInfoService.add();
        return ret ;
    }

@Transactional作用的范围

  • 修饰方法时只能应用到public方法上,否则不生效
  • 修饰类时表明该注解对该类中的所有public方法都生效

注意一般推荐直接应用到某个方法上,因为直接应用到一个类上,如果这个类有很多个public方法同时开启事务会造成一系列的问题,下面事务的传播机制会讲到

@Transactional工作原理

@Transactional 是基于 AOP 实现的,AOP 又是通过动态代理实现的。如果目标对象实现了接⼝,默认情况下会采用JDK 的动态代理,如果目标对象没有实现接口,会使用CGLIB 动态代理。 @Transactional 在开始执行业务之前,通过代理先开启事务,在执行成功之后再提交事务。如果中途遇到的异常,则回滚事务

事务的隔离级别

事务的四大特性:

  1. 原子性:一个事务中的所有操作要么一起完成,要么一起失败,不会在中途某个环节结束,在执行过程中如果发生异常会回滚到事务开始之前的状态
  2. 持久性:事务处理结束后,对数据的修改就是永久的,即便系统故障也不会丢失
  3. 一致性:在事务开始之前和事务结束以后,数据库的完整性没有被破坏。这就说明写入的数据必须完全符合所有的预设规则,这包含数据的精确度、串联性以及后续数据库可以自发性地完成预定的⼯ 作
  4. 隔离性:数据库允许多个并发事务同时对其数据进行读写和修改的能力,隔离性可以防止多个事务并发执行时由于交叉执行而导致数据的不⼀致

事务隔离分为不同级别,包括读未提交(read uncommitted)、读提交(read committed)、可重复读(repeatable read)和串行化 (serializable)

为了保障多个并发事务执行更可控,更符合操作者预期,需要对事务的隔离级别进行设置

Spring中隔离级别的设置

Spring 中事务隔离级别可以通过 @Transactional 中的 isolation 属性进⾏设置,如下图:

 Spring事务的隔离级别有五种:

  1. Isolation.READ_UNCOMMITTED:读未提交,也叫未提交读,该隔离级别的事务可以看到其他事务中未提 交的数据。该隔离级别因为可以读取到其他事务中未提交的数据,⽽未提交的数据可能会发⽣回滚,因此我们把该级别读取到的数据称之为脏数据,把这个问题称之为脏读。简单理解脏读:当事务A还在进行写操作时,事务B对其进行了读取,此时事务A可能会进行回滚,因此事务B之前读到的数据可能会与事务A提交的数据不一致,上述事务B读到的数据就是脏数据,也就是脏读
  2. Isolation.READ_COMMITTED:读提交,该隔离级别的事务能读取到已经提交事务的数据, 因此它不会有脏读问题。但由于在事务的执⾏中可以读取到其他事务提交的结果,所以在不同时间的相同 SQL查询中,可能会得到不同的结果,这种现象叫做不可重复读
  3. Isolation.REPEATABLE_READ:可重复读,是 MySQL中的默认事务隔离级别,它能确保同⼀事务多次查询 的结果⼀致。但也会有新的问题,比如当此级别的事务正在执行时,另⼀个事务成功的插⼊了某条数据,但因为它每次查询的结果都是⼀样的,所以会导致查询不到这条数据,自己重复插⼊时又失败。明明在事务中查询不到这条信息,但自己就是插⼊不进去,这就叫幻读 
  4. Isolation.SERIALIZABLE:串行化,事务最高隔离级别,它会强制事务排序,使之不会发生冲突,从而解决了以上提到的所有问题,但因为执行效率低,所以真正使用的场景并不多
  5. Isolation.DEFAULT:以连接的数据库的事务隔离级别为主

事务的传播机制

什么是事务的传播机制?

事务的传播机制规定了多个包含事务的方法在相互调用时,事务是如何在这些方法间进行传递的

事务隔离级别保证了多个并发事务执行时的稳定性,事务传播机制是保证⼀个事务在多个调用方法间的稳定性

事务的传播机制有哪些?

Spring 事务传播机制包含以下 7 种:

  1. propagation.REQUIRED:默认的事务传播级别,它表示如果当前存在事务,则加入该事务;如果当前没有事务,则创建⼀个新的事务
  2. propagationSUPPORTS:如果当前存在事务,则加入该事务;如果当前没有事务,则以非事务的方式继续运行
  3. propagation.MANDATORY:(mandatory:强制性)如果当前存在事务,则加入该事务;如果当前没有事务,则抛出异常
  4. propagation.REQUIRES_NEW:表示创建⼀个新的事务,如果当前存在事务,则把当前事务挂起。也就是说不管外部方法是否开启事务,Propagation.REQUIRES_NEW 修饰的内部方法会新开启自己的事务,且开启的事务相互独立,互不干扰
  5. propagation.NOT_SUPPORTED:以非事务运行,如果当前存在事务,则把当前事务挂起
  6. propagation.NEVER:以非事务方式运行,如果当前存在事务,则抛出异常
  7. propagation.NESTED:如果当前存在事务,则创建⼀个事务作为当前事务的嵌套事务来运行;如果当前没有事务,则该取值等价于 PROPAGATION_REQUIRED

Spring 中事务传播机制可以通过 @Transactional 中的 propagation 属性进⾏设置,如下图:

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值