【JavaEE】Spring事务

news2025/6/3 9:50:27

目录

  • 一、事务简介
  • 二、Spring事务的实现
    • 2.1 事务的操作
    • 2.2 分类
      • 2.2.1 Spring编程式事务
      • 2.2.2 Spring 声明式事务 @Transactional
        • 2.2.2.1 @Transactional 详解
          • 2.2.2.1.1 rollbackFor
          • 2.2.2.1.2 Isolation
          • 2.2.2.1.3 propagation

一、事务简介

事务:事务是⼀组操作的集合,是⼀个不可分割的操作。事务会把所有的操作作为⼀个整体,⼀起操作。所以这组操作要么同时成功,要么同时失败。

二、Spring事务的实现

2.1 事务的操作

事务的操作主要有三步:

  1. 开启事start transaction / begin (⼀组操作前开启事务)
  2. 提交事务: commit (这组操作全部成功,提交事务)
  3. 回滚事务: rollback (这组操作中间任何⼀个操作出现异常,回滚事务)

2.2 分类

Spring 中的事务操作分为两类:

  1. 编程式事务(⼿动写代码操作事务)
  2. 声明式事务(利⽤注解⾃动开启和提交事务)

2.2.1 Spring编程式事务

SpringBoot 内置了两个对象:

  1. DataSourceTransactionManager 事务管理器。⽤来获取事务(开启事务),提交或回滚事务
  2. TransactionDefinition 是事务的属性,在获取事务的时候需要将 TransactionDefinition 传递进去从⽽获得⼀个事务 TransactionStatus

示例:

package com.example.springtransdemo.controller;


import com.example.springtransdemo.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.TransactionStatus;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RequestMapping("/user")
@RestController
public class UserController {
      @Autowired
      private UserService userService;
      //事务属性
      @Autowired
      private TransactionDefinition definition;
      //事务管理器
      @Autowired
      private DataSourceTransactionManager transactionManager;
      @RequestMapping("/registry")
      public String registry(String name,String password) {
       //开启事务
       TransactionStatus transaction = transactionManager.getTransaction(definition);
       //⽤⼾注册
       userService.registryUser(name, password);
       //提交事务
       transactionManager.commit(transaction);
       //回滚事务
       //transactionManager.rollback(transaction);
       return "注册成功";
      }
}

当我们不提交时可以在数据库中添加字段,回滚后就不会在数据库中添加字段,提交和回滚方法不能在同一个事务中调用。

2.2.2 Spring 声明式事务 @Transactional

使用这个注解需要添加依赖,但是如果已经添加了MyBatis的依赖,那么就包含了下面需要引入的依赖的内容。

<dependency>
 <groupId>org.springframework</groupId>
 <artifactId>spring-tx</artifactId>
</dependency>

注解的应用,在需要使用到事务的方法上加上注解,就会自动提交事务状态。当发⽣了没有处理的error和RunTimeException异常(默认情况下)的时候,就会自动回滚。
例如上面的代码就可以改为:

        @RequestMapping("/registry")
        @Transactional
        public String registry(String name,String password) {
            //⽤⼾注册
            userService.registryUser(name, password);
            return "注册成功";
        }

那么当我们就是要在捕获处理了异常后,还是将事务进行回滚时,我们就可以手动回滚使用TransactionAspectSupport类下使用currentTransactionStatus方法获取状态,使用isRollbackOnly方法回滚。

 @RequestMapping("/registry")
        @Transactional
        public String registry(String name,String password) {
            //⽤⼾注册
            userService.registryUser(name, password);
            try{
                int a = 10 / 0;
            } catch (Exception e) {
                log.error("错误");
                TransactionAspectSupport.currentTransactionStatus().isRollbackOnly();
            }
            return "注册成功";
        }
2.2.2.1 @Transactional 详解

修饰范围:

  • 修饰类时,就是修饰类中的所用访问修饰限定符为public的方法。
  • 修饰方法时,只能修饰访问修饰限定符为public的方法。

@Transactiona 常见三大属性:

  1. rollbackFor:异常回滚属性。指定能够触发事务回滚的异常类型。可以指定多个异常类型。
  2. Isolation:事务的隔离级别。默认值为 Isolation.DEFAULT。
  3. propagation:事务的传播机制。默认值为 Propagation.REQUIRED 。
2.2.2.1.1 rollbackFor

@Transactional 默认只在遇到运⾏时异常RunTimeException和Error时才会回滚。

例如执行下面的操作的时候,事务不会回滚,数据库中还是会添加数据。

        @RequestMapping("/registry")
        @Transactional
        public String registry(String name,String password) throws IOException {
            //⽤⼾注册
            userService.registryUser(name, password);
            if(true) {
                throw new IOException();
            }
            return "注册成功";
        }

但是我们加上属性rollbackFor就会在发生rollbackFor指定的异常的时候回滚。

        @RequestMapping("/registry")
        @Transactional(rollbackFor = Exception.class)
        public String registry(String name,String password) throws IOException {
            //⽤⼾注册
            userService.registryUser(name, password);
            if(true) {
                throw new IOException();
            }
            return "注册成功";
        }

还有与rollbackFor相似作用的属性:

  • rollbackFor :使用class作为值,在发生该异常的时候回滚。
  • rollbackForClassName:使用类名作为值,在发生该异常的时候回滚。
  • noRollbackFor :使用class作为值,在发生该异常的时候不回滚。
  • noRollbackForClassName:使用类名作为值,在发生该异常的时候不回滚。

    当我们同时使用@Transactionsl的noRollbackFor和rollbackFor对同一异常类处理,后使用的会覆盖前面的。例如 @Transactional(rollbackFor = IOException.class, noRollbackFor = IOException.class)生效的是noRollbackFor = IOException.class
2.2.2.1.2 Isolation

Spring事务的隔离级别有以下几种值:

  • DEFAULT:数据库是什么隔离级别,这个方法就还是什么隔离级别。

剩下的都对应MySQL的隔离级别。

  1. 读未提交(READ_UNCOMMITTED):读未提交,也叫未提交读。该隔离级别的事务可以看到其他事务中
    未提交的数据,会有脏读问题。
  2. 读提交(READ_COMMITTED):读已提交,也叫提交读。该隔离级别的事务能读取到已经提交事务的数据,该隔离级别不会有脏读的问题。
  3. 可重复读(REPEATABLE_READ):事务不会读到其他事务对已有数据的修改,即使其他事务已提交。也就可以确保同⼀事务多次查询的结果⼀致,但是其他事务新插⼊的数据,是可以感知到的,这也就引发了幻读问题。
  4. 串⾏化(SERIALIZABLE):序列化,事务最⾼隔离级别。它会强制事务排序,使之不会发⽣冲突,从⽽解
    决了脏读,不可重复读和幻读问题,但因为执⾏效率低,所以真正使⽤的场景并不多。
2.2.2.1.3 propagation

事务的传播机制有以下七种。

我们以A方法调用B方法为例解释:

  1. Propagation.REQUIRED :默认的事务传播级别,如果当前存在事务,则加⼊该事务,如果当前没有事务,则创建⼀个新的事务。如果A方法有事务,B直接就加入,A没有事务B创建一个事务。
  2. Propagation.SUPPORTS :如果当前存在事务,则加⼊该事务。如果当前没有事务,则以⾮事务的⽅式继续运⾏。如果A方法有事务,B直接就加入,A没有事务B也没有事务。
  3. Propagation.MANDATORY :强制性。如果当前存在事务,则加⼊该事务。如果当前没有事务,则抛出异常。如果A方法有事务,B直接就加入,A没有事务抛异常。
  4. Propagation.REQUIRES_NEW :创建⼀个新的事务,如果当前存在事务,则把当前事务挂起。也就是说不管外部⽅法是否开启事务,Propagation.REQUIRES_NEW 修饰的内部⽅法都会新开启⾃⼰的事务,且开启的事务相互独⽴,互不⼲扰。如果A方法有事务,B创建一个事务,两个事务互不影响,A没有事务,B也会创建一个事务。
  5. Propagation.NOT_SUPPORTED :以⾮事务⽅式运⾏,如果当前存在事务,则把当前事务挂起(不⽤)。如果A方法有事务,B创建一个事务,使用B创建的事务,A没有事务B也没有。
  6. Propagation.NEVER :以⾮事务⽅式运⾏,如果当前存在事务,则抛出异常。如果A方法有事务,抛异常,A没有事务B也没有。
  7. Propagation.NESTED :如果当前存在事务,则创建⼀个事务作为当前事务的嵌套事务来运⾏。如果当前没有事务,则该取值等价于 PROPAGATION_REQUIRED 。如果A方法有事务,B创建一个事务,A的事务相当于B的父事务,A没有事务,B也会创建一个事务。
传播行为当前有事务当前无事务
REQUIRED加入事务新建事务
SUPPORTS加入事务非事务执行
MANDATORY加入事务抛出异常
REQUIRES_NEW挂起当前事务并新建事务新建事务
NOT_SUPPORTED挂起当前事务并以非事务执行非事务执行
NEVER抛出异常非事务执行
NESTED创建嵌套事务新建事务

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2394914.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Android15 userdebug版本不能remount

背景描述&#xff1a; 最近调试Android Vendor Hal的时候发现一个奇怪的现象: android userdebug版本刷到设备中&#xff0c;执行adb root没提示错误&#xff0c;但是没有获取到root权限。 Android设备运行的系统版本有三种情况&#xff1a;user版本、userdebug版本和eng版本…

R包安装报错解决案例系列|R包使用及ARM架构解决data.table安装错误问题

有不少同学是Mac系统的&#xff0c;分析过程中会发现部分R包总是安装不成功&#xff0c;这是因为部分R包基于windowsx86架构编译的&#xff0c;最常见的就是含 C/C/Fortran 的包&#xff0c;对于初学者都是建议linux和win去做&#xff0c;Windows 通常直接安装预编译好的二进制…

Linux上安装MongoDB

目录 一、在Linux系统安装MongoDB服务器 1、下载MongoDB 2、上传MongoDB并解压 3、创建必要目录 4、配置环境变量 5、创建配置文件 6、启动命令 7、验证安装 二、在Linux系统安装MongoDB客户端Shell 1、下载MongoDB Shell 2、上传MongoDB Shell并解压 3、配置环境变…

Redis最佳实践——安全与稳定性保障之访问控制详解

Redis 在电商应用的安全与稳定性保障之访问控制全面详解 一、安全访问控制体系架构 1. 多层级防护体系 #mermaid-svg-jpkDj2nKxCq9AXIW {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-jpkDj2nKxCq9AXIW .error-ico…

【华为开发者空间 x DeepSeek】服务器运行Ollama并在本地调用

文章概述 本文介绍了如何在 华为开发者空间 中快速部署并使用 Ollama 模型运行框架&#xff0c;并结合 deepseek-r1 模型进行本地或远程交互推理。内容涵盖环境准备、模型配置、网卡绑定、内网穿透、API调用等多个环节&#xff0c;适合希望在华为云上快速搭建本地类大模型推理…

STM32之IIC(重点)和OLED屏

内部集成电路概述 基本概念 内部集成电路&#xff08;Inter Integrated Circuit&#xff09;的简称叫做IIC或者I2C&#xff0c;是一种简单的、半双工同步通信的串行通信接口&#xff0c;IIC总线是上世纪80年代&#xff08;1982年&#xff09;由飞利浦公司设计出来&#xff0c…

学习海康VisionMaster之表面缺陷滤波

一&#xff1a;进一步学习了 今天学习下VisionMaster中的表面缺陷滤波&#xff1a;简单、无纹理背景的表面缺陷检测&#xff0c;可以检测表面的异物&#xff0c;缺陷&#xff0c;划伤等 二&#xff1a;开始学习 1&#xff1a;什么表面缺陷滤波&#xff1f; 表面缺陷滤波的核心…

游戏引擎学习第314天:将精灵拆分成多个层

回顾并为今天的工作做准备 我们今天继续昨天开始的工作&#xff0c;现在我们要回到渲染中处理 Z 值的最终环节。我们目前已经有一个我们认为还算合理的排序方式&#xff0c;虽然可能还需要在接下来的过程中进行一些调整&#xff0c;但总体上已经有了一个明确的方向。 我们已经…

【学习笔记】深度学习-梯度概念

一、定义 梯度向量不仅表示函数变化的速度&#xff0c;还表示函数增长最快的方向 二、【问】为什么说它表示方向&#xff1f; 三、【问】那在深度学习梯度下降的时候&#xff0c;还要判断梯度是正是负来更新参数吗&#xff1f; 假设某个参数是 w&#xff0c;损失函数对它的…

【数据结构】图的存储(邻接矩阵与邻接表)

图的存储结构 因为图中既有节点&#xff0c;又有边(节点与节点之间的关系)&#xff0c;因此&#xff0c;在图的存储中&#xff0c;只需要保存&#xff1a;节点和边关系即可。 节点保存比较简单&#xff0c;只需要一段连续空间即可&#xff0c;那边关系该怎么保存呢&#xff1…

tomcat yum安装

使用yum安装 yum install -y java-1.7.0-openjdk* tomcat* --disablerepoepel## java-1.7.0-openjdk* 注意&#xff1a;最终安装的是java-1.8.0版本## --disablerepoepel 禁用&#xff1a;EPEL源&#xff0c;防止版本冲突 java -version (2) 启停&#xff1a;Tomcat 7 s…

从翻译后修饰角度解析人工合成途径与底盘细胞的适配性-文献精读136

Compatibility between synthetic pathway and chassis cells from the viewpoint of post-translational modifications 从翻译后修饰角度解析人工合成途径与底盘细胞的适配性 摘要 揭示工程化设计的人工合成途径与底盘细胞整体代谢网络的交互作用及适配性机制是合成生物学研…

Cesium快速入门到精通系列教程一

一、打造第一个Cesium应用 1、官方渠道下载Cesium&#xff08;可选择历史版本&#xff09; ​​GitHub Releases页面​​ 访问 Cesium GitHub Releases&#xff0c;此处列出了所有正式发布的版本。 通过标签&#xff08;如 v1.95.0&#xff09;选择目标版本&#xff0c;下载…

[Windows] 剪映 视频编辑处理

附链接&#xff1a;夸克网盘分享&#xff08;点击蓝色字体自行保存下载&#xff09;

决策树 GBDT XGBoost LightGBM

一、决策树 1. 决策树有一个很强的假设&#xff1a; 信息是可分的&#xff0c;否则无法进行特征分支 2. 决策树的种类&#xff1a; 2. ID3决策树&#xff1a; ID3决策树的数划分标准是信息增益&#xff1a; 信息增益衡量的是通过某个特征进行数据划分前后熵的变化量。但是&…

stm32 / arduino TPL0401A使用教程

这是在给英国的一个学生讲课时用到的一个芯片&#xff0c;做一个dcdc的反馈电路&#xff0c;刚开始用的不是这个&#xff0c;后来发现国内这个芯片用的挺成熟&#xff0c;就选择了这个。 芯片说明 首先我买的是TPL0401A,我发现淘宝上卖的都是A&#xff0c;其实想用C&#xff0…

数据结构与算法之单链表面试题(新浪、百度、腾讯)

单链表面试题&#xff08;新浪、百度、腾讯&#xff09; 求单链表中的有效节点的个数 public int getCount(HeroNode head) {Hero1 cur head.getNext();int count 0;while(cur ! null) {count;cur cur.getNext();}return count;}查找单链表中的倒数第k个结点【新浪面试题】…

单板机8088C语言计划

计划将原来用汇编写的小程序&#xff0c;用C语言重新写一遍 计划2个月能完成 然后再试试&#xff0c;能不能用C写一下固件BootLoad 和一个类似Dos时代的Debug调试器

一周学会Pandas2之Python数据处理与分析-数据重塑与透视-pivot() - 透视 (长 -> 宽,有限制)

锋哥原创的Pandas2 Python数据处理与分析 视频教程&#xff1a; 2025版 Pandas2 Python数据处理与分析 视频教程(无废话版) 玩命更新中~_哔哩哔哩_bilibili pivot() 是 pandas 中用于数据重塑的核心方法&#xff0c;它将长格式数据转换为宽格式数据&#xff0c;与 melt() 方…

机器学习中无监督学习方法的聚类:划分式聚类、层次聚类、密度聚类

1.定义和特点 2.划分式聚类&#xff1a;K-Means 、 K-Medoids 3.层次聚类&#xff1a;树状图 4.密度聚类&#xff1a;DBSCAN 5.聚类的应用 一、定义和特点 机器学习中的无监督学习聚类是一种通过数据内在结构将样本分组的技术&#xff0c;无需预先标注的类别标签。 它的核心目…