Spring事务与事务传播

这篇具有很好参考价值的文章主要介绍了Spring事务与事务传播。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

Spring事务与事务传播

一、什么是事务?

事务:事务是一组操作的集合,是不可分割的基本单位,要么全部成功,要么全部失败
我们在MySQL中使用事务有三步操作:开启事务,提交事务,回滚事务

-- 开启事务
start transaction;

-- 执行具体业务

-- 提交事务
commit;

-- 回滚事务
rollback

事务的四大特性(ACID): 原子性、一致性、持久性、隔离性
原子性(Atomicity):一个事务的操作,要么全部完成,要么全部不完成
一致性(Consistency):事务开始之前和事务结束之后,数据库的完整性没有被破坏
持久性(Isolation):事务提交后,对数据的修改就是永久的
隔离性(Durability):数据库允许多个并发事务同时对其数据读写和修改的能力,隔离性可以防止多个事务并发执行时导致的数据不一致
隔离级别是可以设置的

事务的隔离级别: 在数据库中,多个事务并发执行时,各个事务之间是相互隔离的,每个事务之间都不能相互干扰。为了保证并发事务的正确性和一致性,数据库管理系统(DBMS)提供了四种事务隔离级别,分别为读未提交、读已提交、可重复读和串行化。

读未提交(Read Uncommitted)
在该隔离级别下,一个事务可以读取另一个事务尚未提交的数据,不仅如此,它可能还会读到一些脏数据(Dirty Read)。在该级别下,数据的一致性和完整性得不到保障,不推荐使用。

读已提交(Read Committed)
在该隔离级别下,一个事务只能读取另一个事务已经提交的数据,避免了脏读的问题,但是可能会出现不可重复读(Non-Repeatable Read)的问题。即同一事务中,多次读取同一数据可能会得到不同的结果,因为其他事务可能在两次读取之间提交了修改。

可重复读(Repeatable Read)
在该隔离级别下,一个事务在执行期间多次读取同一数据时,能够保证所读取的数据一定是事务开始时的状态,避免了不可重复读的问题,但是可能会出现幻读(Phantom Read)问题,即两次查询间新增数据的影响。

串行化(Serializable)
在该隔离级别下,所有事务串行执行,避免了脏读、不可重复读和幻读的问题,但是实际应用中可能会导致性能严重下降,因此该级别一般只在特殊情况下使用。

默认隔离级别为REPEATABLE READ
Spring事务与事务传播

我们可以使用以下SQL查询全局事务隔离级别和当前连接的事务隔离级别:

select @@global.tx_isolation,@@tx_isolation;

Spring事务与事务传播

二、Spring事务实现

Spring中的事务分为两类:
1.编程式事务(手动操作)
2.声明式事务(自动提交事务)

编程式事务

SpringBoot内置了两个对象,DataSourceTransactionManager用来获取事务(开启事务、提交事务、回滚事务)。TransactionDefinition是事务的属性,在获取事务时,需要将TransactionDefinition传递进去获取一个TransactionStatus

@RestController
@RequestMapping("/user")
public class UserController {

    @Autowired
    private UserService userService;
    @Autowired
    private DataSourceTransactionManager transactionManager;
    @Autowired
    private TransactionDefinition transactionDefinition;

    @RequestMapping("/del")
    public int del(Integer id) {
        if(id != null && id > 0) {
            //开启事务
            TransactionStatus transactionStatus =
                    transactionManager.getTransaction(transactionDefinition);
            //删除用户业务操作
            int result = userService.del(id);
            System.out.println("删除了: " + result);
            // 提交事务/回滚事务
//            transactionManager.commit(transactionStatus); //提交事务
            transactionManager.rollback(transactionStatus); //回滚事务
        }
        return 0;
    }
}

Spring事务与事务传播
Spring事务与事务传播
Spring事务与事务传播
数据库原始数据:
Spring事务与事务传播
Spring事务与事务传播
Spring事务与事务传播
这里显示操作成功,我们来看看我们数据库数据发生变化了没
Spring事务与事务传播
我们可以发现,事务成功的进行了回滚,但是这样的方式太繁琐了,我们来学习更简单的声明式事务

声明式事务

声明式事务我们只需要在方法上@Transactional注解就可以实现,无需手动进行开启事务和提交事务,进入方法自动开启,执行完毕自动提交,发生异常后会自动回滚事务

@RestController
@RequestMapping("/user2")
public class UserController2 {

    @Autowired
    private UserService userService;

    @Transactional
    @RequestMapping("/del")
    public int del(Integer id) {
        if(id == null || id <= 0) {
            return 0;
        }
        return userService.del(id);
    }
}

这种是没有异常的异常,我们会进行commit,我们目前数据库数据:
Spring事务与事务传播
Spring事务与事务传播

Spring事务与事务传播

我们可以发现成功的删除了数据库的一条数据:
Spring事务与事务传播
我们来在业务中加上一段异常代码:

@RestController
@RequestMapping("/user2")
public class UserController2 {

    @Autowired
    private UserService userService;

    @Transactional
    @RequestMapping("/del")
    public int del(Integer id) {
        if(id == null || id <= 0) {
            return 0;
        }
        int result = userService.del(id);
        int n = 1 / 0; //异常业务
        return result;
    }
}

我们再来进行删除操作:
Spring事务与事务传播

Spring事务与事务传播
我们可以看到我们的控制台信息,成功的进行了删除操作
Spring事务与事务传播
同时报了一个算术异常
Spring事务与事务传播
我们查看数据库信息,发现当发生异常时会自动进行回滚操作。

三、@Transactional的使用

@Transactional的作用范围:@Transactional既可以用来修饰方法也可以用来修饰类
1.修饰方法:只能应用到public方法上,否则不生效,推荐用法
2.修饰类:表明该注解对所有的public方法都生效

参数作用

我们可以通过设置@Transactional的一些参数来决定事务的一些具体的功能
Spring事务与事务传播

Spring事务的隔离级别

Spring的事务隔离级别是有以下5种的
Spring事务与事务传播
1.DEFAULT:使用底层数据库默认的隔离级别。
2.READ_UNCOMMITTED:允许读取还未提交的数据,会出现脏读、不可重复读和幻读等问题。
3.READ_COMMITTED:只能读取已经提交的数据,避免了脏读的问题,但是可能出现不可重复读和幻读的问题。
4.REPEATABLE_READ:保证同一事务中多次读取同一记录结果是一致的,避免了脏读和不可重复读的问题,但是仍然可能出现幻读的问题。
5.SERIALIZABLE:最高的隔离级别,保证事务串行执行,避免了脏读、不可重复读和幻读等问题,但是影响系统性能。

默认情况下,Spring 会使用底层数据库的默认隔离级别,通常是READ_COMMITTED 级别。可以通过事务管理器的 setDefaultTransactionIsolation() 方法或在事务注解中使用 isolation 属性来设置隔离级别,例如:

@Transactional(isolation = Isolation.DEFAULT)
    @RequestMapping("/del")
    public int del(Integer id) {
    }

Spring事务与事务传播

Spring事务与事务传播

事务失效的场景

常见的事务失效场景有以下三种:
1.异常捕获处理: @Transactional 在异常被捕获的情况下,不会进行事务自动回滚
Spring事务与事务传播
我们进行操作之前的数据库数据,我们进行try,catch处理
Spring事务与事务传播
Spring事务与事务传播
Spring事务与事务传播
我们发现程序抛出了异常,但并没有进行回滚操作
Spring事务与事务传播
原因:事务通知只有自己捕捉到了目标抛出的异常,才能进行后续的回滚操作,如果目标自己处理掉了异常,事务无法知悉

解决方案: 在catch块中添加throw new RuntimeException(e)抛出
Spring事务与事务传播
我们将数据恢复
Spring事务与事务传播
Spring事务与事务传播
Spring事务与事务传播
我们来进行操作时,进行了回滚操作

2.抛出检查异常:
Spring事务与事务传播
Spring事务与事务传播
Spring事务与事务传播
我们的事务未进行回滚操作
原因:Spring默认值只会回滚非检查异常

解决方案: 配置rollbackFor属性
Spring事务与事务传播
Spring事务与事务传播
在进行操作时,事务成功的进行了回滚操作

3.非public方法导致的事务失效:
Spring事务与事务传播
Spring事务与事务传播
Spring事务与事务传播
事务没有进行回滚操作
原因:Spring为方法创建代理,添加事务通知、前提条件都是该方法为public

解决方案: 改为Public

@Transactional工作原理

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

四、Spring事务传播机制

Spring事务传播机制定义了多个包含事务的方法,相互调用时
为什么需要事务传播机制?事务隔离级别不够用吗?
事务隔离级别是保证多个并发事务执行是可控的,而事务传播机制是保证一个事务在多个调用方法间是可控的。
事务隔离级别是为了解决多个事务同时调用一个数据库的问题:

Spring事务与事务传播
事务传播机制是解决一个事务在多个方法中传递的问题:

Spring事务与事务传播

Spring有哪些事务传播机制?

Spring 支持以下七种事务传播机制:

1.PROPAGATION_REQUIRED:默认值,如果当前存在一个事务,则加入该事务;否则新建一个事务。这是最常见的传播机制,也是大多数情况下使用的传播机制。如果外围方法已经启动了事务,那么内部方法就会在该事务中运行;如果外围方法尚未启动事务,则内部方法会启动一个新的事务。

2.PROPAGATION_REQUIRES_NEW:将当前事务挂起,开启一个新的事务进行执行。如果当前存在事务,则将当前事务挂起并启动一个新事务;如果当前没有事务,则开启一个新的独立事务。
3.PROPAGATION_SUPPORTS:如果当前存在事务,则加入该事务;否则以非事务方式继续运行。若外围方法有事务,则使用该事务;若外围方法没有事务,则直接执行。
4.PROPAGATION_NOT_SUPPORTED:以非事务方式运行,如果当前存在事务,则将该事务挂起。若外围有事务,则将当前事务挂起,然后以非事务方式执行;若外围没有事务,则直接以非事务方式执行。
5.PROPAGATION_NEVER:表示当前方法不应该执行在事务上下文中。如果当前事务存在,则抛出异常。即表示当前方法不能够在事务环境中运行。
6.PROPAGATION_MANDATORY:当前方法必须在事务上下文中运行,否则抛出异常。要求当前环境中必须存在事务,否则会抛出异常。
7.PROPAGATION_NESTED:如果当前存在事务,则开启一个子事务进行执行;如果当前不存在事务,则新建一个事务进行执行。嵌套事务和普通事务的区别是,嵌套事务可以独立于外围事务进行提交或回滚,而不影响外围事务的状态。如果外围事务已经提交或回滚,则子事务也会被提交或回滚,但如果子事务发生异常而回滚,则外围事务可以选择回滚或不回滚。

事务传播机制可以分为以下三类:
Spring事务与事务传播
我们可以更形象的看一下下述图来理解(别的大佬的图):
Spring事务与事务传播文章来源地址https://www.toymoban.com/news/detail-465569.html

到了这里,关于Spring事务与事务传播的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【JavaEE进阶】Spring事务和事务传播机制

    Spring 事务是 Spring 框架提供的一种机制,用于 管理数据库操作或其他资源的一组相关操作 ,以确保它们在一个原子、一致、可靠和隔离的执行单元内进行。事务用于维护数据的完整性并支持并发访问数据库时的数据一致性。 Spring 事务的主要特点包括: 原子性(Atomicity):

    2024年02月09日
    浏览(63)
  • Spring事务传播机制

    编程式事务管理:通过  TransactionTemplate 或者 TransactionManager 手动管理事务,实际应用中很少使用,这不是本文的重点,就不在这里赘述。 声明式事务管理:使用场景最多,也是最推荐使用的方式,直接加上@Transactional注解即可。 @Transactional 注解是用于声明事务性方法的注解

    2024年01月16日
    浏览(39)
  • Spring事务传播机制解析

    在Java的Spring框架中,事务管理是保证应用数据一致性和可靠性的关键。Spring提供了灵活的事务传播机制,它定义了事务边界,以及在嵌套方法调用时如何处理事务。本文旨在深入探讨Spring的事务传播行为,帮助开发者更好地理解和运用这一重要特性。 事务传播机制指的是在

    2024年01月16日
    浏览(39)
  • spring的事务传播机制

    嫌弃内容代码复杂的可直接看思维导图大纲即可 指的就是当一个事务方法被另一个事务方法调用时,这个事务方法应该如何进行 默认,当前存在事务,则加入该事务;不存在事务,创建新事务。 始终以新的事务运行,当前存在事务,则挂起原事务;不存在事务,创建新事务

    2023年04月23日
    浏览(53)
  • 一文详解Spring事务传播机制

    目录 背景 Spring事务 @Transactional注解 使用场景 失效场景 原理 常用参数 注意 事务传播机制 处理嵌套事务流程 主事务为REQUIRED子事务为REQUIRED 主事务为REQUIRED子事务为REQUIRES_NEW 主事务为REQUIRED子事务为NESTED 实现方式 源码解析 我们在使用Spring管理数据库事务的时候很方便,只

    2023年04月26日
    浏览(48)
  • 【Spring】深入理解 Spring 事务及其传播机制

    在 Spring 框架中,事务(Transaction)是一种用于管理数据库操作的机制,旨在 确保数据的 一致性、可靠性和完整性 。事务可以将一组数据库操作(如插入、更新、删除等)视为一个单独的执行单元,要么 全部成功地执行,要么全部回滚 。这样可以确保数据库在任何时候都保

    2024年02月12日
    浏览(61)
  • spring事务管理详解和实例(事务传播机制、事务隔离级别)

    目录 1 理解spring事务 2 核心接口 2.1 事务管理器 2.1.1 JDBC事务 2.1.2 Hibernate事务 2.1.3 Java持久化API事务(JPA) 2.2 基本事务属性的定义 2.2.1 传播行为 2.2.2 隔离级别 2.2.3 只读 2.2.4 事务超时 2.2.5 回滚规则 2.3 事务状态 3 编程式事务 3.1 编程式和声明式事务的区别 3.2 如何实现编程式

    2024年02月06日
    浏览(44)
  • Spring事务的四大特性+事务的传播机制+隔离机制

    原子性是指事务是一个不可分割的工作单位,事务中的操作要么都发生,要么都不发生。 事务是一个原子操作, 由一系列动作组成。 组成一个事务的多个数据库操作是一个不可分割的原子单元 ,只有所有的操作执行成功,整个事务才提交。 事务中的任何一个数据库操作失败

    2024年01月20日
    浏览(40)
  • Spring事务传播的7种机制

    1. Propagation.REQUIRED:默认的事务传播级别,它表示如果当前存在事务,则加入该事务;如果 当前没有事务,则创建一个新的事务。 2. Propagation.SUPPORTS:如果当前存在事务,则加入该事务;如果当前没有事务,则以非事务的 方式继续运行。 3. Propagation.MANDATORY:(mandatory:强制

    2024年02月09日
    浏览(47)
  • Spring事务切面_传播属性(8)

    目录 1. 传播属性 2. 案例分享 2.1 测试说明 2.2  Propagation.REQUIRED 演示 案例1: 案例2: 案例3: 案例4: 总结1: 案例5: 案例6: 特殊的传播属性 NESTED 错误使用 案例6的解决方案: 3. 带着问题看源码 3.1 类分析: 3.2 源码分析 3.2.1 事务创建  3.2.2 事务的链式调用 源码case: 3

    2023年04月10日
    浏览(42)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包