首页 > 其他分享 >Spring的事务管理

Spring的事务管理

时间:2023-12-30 10:36:39浏览次数:23  
标签:事务管理 事务 int Spring PROPAGATION boolean 级别 TransactionStatus


1. 事务概述


1.1 事务的四个特性 ACID 

  • 原子性(Automic):  事务作为一个整体被执行,包含在事务中对数据库的操作,要么全部被执行,要么全部不被执行。
  • 一致性(Consistency): 事务应该保证数据库从一个一致状态转变为另外一个状态。
  • 隔离性(Isolation): 多个事务并发执行时,一个事务的执行不应影响其他事务的执行。
  • 持久性 (Durability) :  已被提交的事务对数据库的修改应该被永久的保存在数据库中。

1.2 事务的隔离级别

首先有如下三个并发问题:

  • 脏读:事务A读取了事务B更新的数据,然后B回滚操作,那么A读取到的数据是脏数据
  • 不可重复读:事务 A 多次读取同一数据,事务 B 在事务A多次读取的过程中,对数据作了更新并提交,导致事务A多次读取同一数据时,结果 不一致。
  • 幻读:系统管理员A将数据库中所有学生的成绩从具体分数改为ABCDE等级,但是系统管理员B就在这个时候插入了一条具体分数的记录,当系统管理员A改结束后发现还有一条记录没有改过来,就好像发生了幻觉一样,这就叫幻读。

MySQL事务隔离级别如下所示:

事务隔离级别

脏读

不可重复读

幻读

读未提交(read-uncommitted)

不可重复读(read-committed)

可重复读(repeatable-read)

串行化(serializable)

2. Spring 中的事务


3 个 核心接口 :PlatformTransactionManager、TransactionStatus、TransactionDefinition。

2.1 PlatformTransactionManager 

PlatformTransactionManager 平台事务管理器。Spring4中的源码如下所示:

public interface PlatformTransactionManager {
    TransactionStatus getTransaction(TransactionDefinition var1) throws TransactionException;

    void commit(TransactionStatus var1) throws TransactionException;

    void rollback(TransactionStatus var1) throws TransactionException;
}
  • TransactionStatus getTransaction(TransactionDefinition var1) throws TransactionException; 获取事务状态
  • void commit(TransactionStatus var1) throws TransactionException;  提交事务
  •  void rollback(TransactionStatus var1) throws TransactionException;  回滚事务

2.2 TransactionDefinition 

TransactionDefinition 事务定义对象,定义了事务规则和获取事务相关信息的方法。Spring4中的源码如下所示:

public interface TransactionDefinition {
    int PROPAGATION_REQUIRED = 0;
    int PROPAGATION_SUPPORTS = 1;
    int PROPAGATION_MANDATORY = 2;
    int PROPAGATION_REQUIRES_NEW = 3;
    int PROPAGATION_NOT_SUPPORTED = 4;
    int PROPAGATION_NEVER = 5;
    int PROPAGATION_NESTED = 6;
    int ISOLATION_DEFAULT = -1;
    int ISOLATION_READ_UNCOMMITTED = 1;
    int ISOLATION_READ_COMMITTED = 2;
    int ISOLATION_REPEATABLE_READ = 4;
    int ISOLATION_SERIALIZABLE = 8;
    int TIMEOUT_DEFAULT = -1;

    int getPropagationBehavior();

    int getIsolationLevel();

    int getTimeout();

    boolean isReadOnly();

    String getName();
}
  •  int getPropagationBehavior();  获取事务的传播行为
  •  int getIsolationLevel(); 获取事务的隔离级别
  • int getTimeout(); 获取事务的超时时间
  •  boolean isReadOnly(); 获取事务是否只读
  •  String getName(); 获取事务对象名称

在TransactionDefinition接口中定义了五个不同的事务隔离级别:

ISOLATION_DEFAULT

这是一个PlatfromTransactionManager默认的隔离级别使用数据库默认的事务隔离级别.另外四个与JDBC的隔离级别相对应 

ISOLATION_READ_UNCOMMITTED

这是事务最低的隔离级别,它充许别外一个事务可以看到这个事务未提交的数据。这种隔离级别会产生脏读,不可重复读和幻像读

ISOLATION_READ_COMMITTED

保证一个事务修改的数据提交后才能被另外一个事务读取。另外一个事务不能读取该事务未提交的数据。这种事务隔离级别可以避免脏读出现,但是可能会出现不可重复读和幻像读。

ISOLATION_REPEATABLE_READ

这种事务隔离级别可以防止脏读,不可重复读。但是可能出现幻像读。它除了保证一个事务不能读取另一个事务未提交的数据外,还保证了避免下面的情况产生(不可重复读)。

ISOLATION_SERIALIZABLE

这是花费最高代价但是最可靠的事务隔离级别。事务被处理为顺序执行。除了防止脏读,不可重复读外,还避免了幻像读。

事务的7种传播级别:

PROPAGATION_REQUIRED 

默认的spring事务传播级别,使用该级别的特点是,如果上下文中已经存在事务,那么就加入到事务中执行,如果当前上下文中不存在事务,则新建事务执行。所以这个级别通常能满足处理大多数的业务场景。

PROPAGATION_SUPPORTS 

从字面意思就知道,supports,支持,该传播级别的特点是,如果上下文存在事务,则支持事务加入事务,如果没有事务,则使用非事务的方式执行。所以说,并非所有的包在transactionTemplate.execute中的代码都会有事务支持。这个通常是用来处理那些并非原子性的非核心业务逻辑操作。应用场景较少。

PROPAGATION_MANDATORY

该级别的事务要求上下文中必须要存在事务,否则就会抛出异常!配置该方式的传播级别是有效的控制上下文调用代码遗漏添加事务控制的保证手段。比如一段代码不能单独被调用执行,但是一旦被调用,就必须有事务包含的情况,就可以使用这个传播级别。

PROPAGATION_REQUIRES_NEW 

从字面即可知道,new,每次都要一个新事务,该传播级别的特点是,每次都会新建一个事务,并且同时将上下文中的事务挂起,执行当前新建事务完成以后,上下文事务恢复再执行。

 

这是一个很有用的传播级别,举一个应用场景:现在有一个发送100个红包的操作,在发送之前,要做一些系统的初始化、验证、数据记录操作,然后发送100封红包,然后再记录发送日志,发送日志要求100%的准确,如果日志不准确,那么整个父事务逻辑需要回滚。

 

怎么处理整个业务需求呢?就是通过这个PROPAGATION_REQUIRES_NEW 级别的事务传播控制就可以完成。发送红包的子事务不会直接影响到父事务的提交和回滚。

PROPAGATION_NOT_SUPPORTED

这个也可以从字面得知,not supported ,不支持,当前级别的特点就是上下文中存在事务,则挂起事务,执行当前逻辑,结束后恢复上下文的事务。

这个级别有什么好处?可以帮助你将事务极可能的缩小。我们知道一个事务越大,它存在的风险也就越多。所以在处理事务的过程中,要保证尽可能的缩小范围。比如一段代码,是每次逻辑操作都必须调用的,比如循环1000次的某个非核心业务逻辑操作。这样的代码如果包在事务中,势必造成事务太大,导致出现一些难以考虑周全的异常情况。所以这个事务这个级别的传播级别就派上用场了。用当前级别的事务模板抱起来就可以了。

PROPAGATION_NEVER

该事务更严格,上面一个事务传播级别只是不支持而已,有事务就挂起,而PROPAGATION_NEVER传播级别要求上下文中不能存在事务,一旦有事务,就抛出runtime异常,强制停止执行!这个级别上辈子跟事务有仇。

PROPAGATION_NESTED

字面也可知道,nested,嵌套级别事务。该传播级别特征是,如果上下文中存在事务,则嵌套事务执行,如果不存在事务,则新建事务。

2.3 TransactionStatus  

TransactionStatus  事务的状态,他描述了某一时间点上事务的状态信息,Spring4中的源码如下所示。

public interface TransactionStatus extends SavepointManager, Flushable {
    boolean isNewTransaction();

    boolean hasSavepoint();

    void setRollbackOnly();

    boolean isRollbackOnly();

    void flush();

    boolean isCompleted();
}
  • boolean isNewTransaction();  获取是否是新事务
  • boolean hasSavepoint(); 获取事务是否存在保存点
  •  void setRollbackOnly(); 设置事务回滚
  • boolean isRollbackOnly(); 获取是否回滚
  • void flush(); 刷新事务
  • boolean isCompleted(); 获取事务是否完成

 4. Spring事务的实现

两种方法:传统的编程式事务 和 声明式事务。

编程式事务,通过编写代码实现事务,包括定义事务的开始,事务正常执行的提交和异常时事务的回滚。

声明式事务,使用 Spring 的 AOP 面向切面编程,又分为基于 xml 的声明式事务 和 使用注解的声明式事务。

参考文献:

  • https://yq.aliyun.com/articles/48893
  • JavaEE 企业级应用开发教程(Spring + SpringMVC + MyBatis)/ 黑马程序员编著. ——北京 :人民邮电出版社,2017.9 (2018.2 重印)

 

标签:事务管理,事务,int,Spring,PROPAGATION,boolean,级别,TransactionStatus
From: https://blog.51cto.com/xuxiangyang/9038463

相关文章

  • Spring 中控制反转 和 依赖注入 的区别和关系
    控制反转(IOC),面向对象的一种设计原则,目的是降低耦合度。依赖注入(DI)是实现控制反转的常见方式,控制反转的另外一种实现方式是 依赖查找。控制反转中的控制指的是自己控制(创建)自己的成员变量,反转指的是由通过自己去控制(创建)成员变量变成由第三方来传递给自身,也就是第三方将自己的依赖......
  • IDEA 中 SpringBoot2 整合 Mybatis 实例实例
    记录在IDEA中 使用SpringBoot2整合Mybatis的实例,环境:Java8+Maven+MySQL8。1. 添加依赖 添加MyBatis依赖,MySQL连接依赖,,数据库用的MySQL8。<!--MyBatis依赖--><dependency><groupId>org.mybatis.spring.boot</groupId><artifactId>mybatis-s......
  • Spring Boot学习随笔- 集成MyBatis-Plus,第一个MP程序(环境搭建、@TableName、@TableId
    学习视频:【编程不良人】Mybatis-Plus整合SpringBoot实战教程,提高的你开发效率,后端人员必备!引言MyBatis-Plus是一个基于MyBatis的增强工具,旨在简化开发,提高效率。它扩展了MyBatis的功能,提供了许多实用的特性,包括强大的CRUD操作、条件构造器、分页插件、代码生成器等。MyBati......
  • spring(自动加载xml装载容器)
    1.实现将DefaultListableBeanFactory类注入到当前AbstractBeanDefinitionReader中2.取出xml内容,并生成beanfinition实例对象,注入到DefaultListableBeanFactory类中的map中。packageorg.springframework.beans.factory.xml;importcn.hutool.core.util.StrUtil;importorg.do......
  • Java+SpringBoot+Maven+TestNG+httpclient+Allure+Jenkins实现接口自动化
    一、方案需求目标:测试左移,测试介入研发过程,验证单接口正常及异常逻辑选用工具:Java、SpringBoot、Maven、TestNG、httpclient、Allure、Jenkins方案:创建测试接口测试工程,参照研发设计文档和设计思路,编写正常及异常用例,直接调用服务端接口,覆盖接口逻辑和验证异常处理,提升接口健壮......
  • 网络安全——SpringBoot配置文件明文加密
    信铁寒胜:这边文章真的说得挺好的。XTHS:第一步、XTHS:第二步、XTHS:第三步、XTHS:第四步!就可以实现了。(但是前提,你要先对你的文本进行加密,然后按照ENC(加密文本),放到配置文件中) 一、前言在日常开发中,项目中会有很多配置文件。比如SpringBoot项目核心的数据库配置、Redis账号密码......
  • Springboot集成Nacos
    1.添加依赖com.alibaba.cloudspring-cloud-starter-alibaba-nacos-discovery2.2.9.RELEASEcom.alibaba.cloudspring-cloud-starter-alibaba-nacos-config2.2.9.RELEASE2.注册中心1、把Nacos的Ip和端口配置配置文件中2、在启动类上加上@EnableDiscoveryClient注解3、同一类的服务可......
  • Springboot集成Nacos
    1.添加依赖com.alibaba.cloudspring-cloud-starter-alibaba-nacos-discovery2.2.9.RELEASEcom.alibaba.cloudspring-cloud-starter-alibaba-nacos-config2.2.9.RELEASE2.注册中心1、把Nacos的Ip和端口配置配置文件中2、在启动类上加上@EnableDiscoveryClient注解3、同一类的服务可......
  • 在SpringBoot中自定义指标并使用Prometheus监控报警
    公众号「架构成长指南」,专注于生产实践、云原生、分布式系统、大数据技术分享在10分钟教你使用Prometheus监控SpringBoot工程中介绍了如何使用Prometheus监控SpringBoot提供的默认指标,这篇介绍如何自定义业务指标,并使用Prometheus进行监控并报警,同时在Grafana进行展现示例......
  • Spring Boot 正式弃用 Java 8。。
    大家好,我是R哥。关注Spring框架的都知道,因为Spring6.0要求最低JDK17+,所以SpringBoot3.0也必须JDK17+了,但是3.0出来的时候,一站式生成项目还是可以选Java8的,如下图所示:这是Spring提供的一站式生成Spring应用的网站,这个网站可以帮助开发人员一键生成符合S......