2023.12.9 关于 Spring Boot 事务传播机制详解

目录

事务传播机制

七大事务传播机制 

支持当前调用链上的事务

Propagation.REQUIRED

Propagation.SUPPORTS

Propagation.MANDATORY

不支持当前调用链上的事务

Propagation.REQUIRES_NEW

Propagation.NOT_SUPPORTED

Propagation.NEVER

嵌套事务

Propagation.NESTED

前置工作

初始化数据库

初始化 实体类

初始化 Mapper 接口

初始化 XML 文件

 重点理解部分

NESTED 和 REQUIRED_NEW 的区别

NESTED 和 REQUIRED 的区别


事务传播机制

  • 事务的传播机制是指在多个事务方法之间调用时,事务如何在这些方法之间传播

七大事务传播机制 

支持当前调用链上的事务

Propagation.REQUIRED

  • 默认的事务传播级别
  • 如果当前没有事务,则新建一个事务,如果当前存在事务,则加入该事务

实例理解


Propagation.SUPPORTS

  • 如果当前方法没有事务,就以非事务方式执行,如果已经存在一个事务中,则加入到这个事务中


Propagation.MANDATORY

  • 如果当前方法没有事务,则抛出异常,如果已经存在一个事务中,则加入到这个事务中

不支持当前调用链上的事务

Propagation.REQUIRES_NEW

  • 创建一个新事务,如果存在当前事务,则挂起当前事务

Propagation.NOT_SUPPORTED

  • 以非事务方式执行,如果存在当前事务,则挂起当前事务

Propagation.NEVER

  • 以非事务方式执行,如果当前事务存在,则抛出异常

嵌套事务

Propagation.NESTED

  • 如果当前存在事务,则在嵌套事务中执行,否则与 REQUIRED 的操作一样

前置工作

  • 此处为了方便下文进行代码测试理解
  • 我们先将准备工作做好

初始化数据库

  • 创建一个 user 表,并添加几条用户信息


初始化 实体类

  • 创建 User 实体类 与 数据库的 user 表字段名相对应
import lombok.Data;@Data
public class User {private int id;private String name;private int age;private String password;private int state;
}

初始化 Mapper 接口

  • 初始化 UserMapper 接口,此处我们添加一个 add 方法

import com.example.demo.entity.User;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;@Mapper
public interface UserMapper {
//    新增用户信息Integer add(User user);
}

初始化 XML 文件

  • 在与 UserMapper 接口相对应的 XML 文件中添加上与 add 方法 相对应的 sql 语句
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.example.demo.mapper.UserMapper"><insert id="add">insert into user(name,age,password) values(#{name},#{age},#{password})</insert>
</mapper>

 重点理解部分

NESTED 和 REQUIRED_NEW 的区别

  • REQUIRED_NEW 是新建一个事务并且新开始的这个事务与原有事务无关
  • 而 NESTED 是当前存在事务时会开启一个嵌套事务
  • 在 NESTED 情况下,父事务回滚时,子事务也会回滚
  • 而 REQUIRED_NEW 情况下,原有事务回滚,不会影响新开启的事务

实例理解

  • 我们创建一个 userController 类,并给 addUser 方法加上 REQUIRED 类型的事务
  •  此时的 addUser 方法,将自动创建一个事务A
  • 注意我们在 addUser 中加入了一个算数异常
import com.example.demo.entity.User;
import com.example.demo.service.LoggerService;
import com.example.demo.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;@RestController
@RequestMapping("/user2")
public class UserController {@Autowiredprivate UserService userService;@RequestMapping("/add")@Transactional(propagation = Propagation.REQUIRED)public String addUser(User user) {
//        调用 userService 的 add 方法int result = userService.add(user);int c = 10/0;return "add 方法:" + (result == 1 ? "新增用户成功": "新增用户失败");}
}
  • 可以看到 userController 类中调用了 add 方法,该方法在 userService 中
  • 此处我们给 add 方法加上 NESTED 类型的事务
  • 因为 addUser 已经创建了一个事务A,所以此处的 add 方法将在 事务A中创建一个嵌套事务
import com.example.demo.entity.User;
import com.example.demo.mapper.UserMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;@Service
public class UserService {@Autowiredprivate UserMapper userMapper;//    新增用户信息@Transactional(propagation = Propagation.NESTED)public int add(User user) {int result = userMapper.add(user);return result;}
}

运行结果:

  • 在浏览器中输入对应的 URL 来访问 addUser 方法
  • 此时我们关注的是 在 NESTED 情况下,父事务回滚时,子事务也会回滚

  • 此处正好为 addUser 方法发生了 算数异常,从而进行了回滚操作
  • 且在抛出算数异常前,就已经调用了 userService.add 方法
  • 如果此处数据库中插入了新用户信息,则代表子事务未进行回滚操作

  • 此时我们查看 user 表,发现新用户未插入,即子事务进行了回滚操作,与预期结果一致

调整 add 方法的事务传播机制

  • 我们将 add 方法改为 REQUIRES_NEW 类型的事务
  • 因为 addUser 已经创建了一个事务A,所以此处的 add 方法将会把 事务A 挂起,另外创建一个 事务B
import com.example.demo.entity.User;
import com.example.demo.mapper.UserMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;@Service
public class UserService {@Autowiredprivate UserMapper userMapper;//    新增用户信息@Transactional(propagation = Propagation.REQUIRES_NEW)public int add(User user) {int result = userMapper.add(user);return result;}
}

运行结果:

  • 在浏览器中输入对应的 URL 来访问 addUser 方法
  • 此时我们关注的是 REQUIRED_NEW 情况下,原有事务回滚,不会影响新开启的事务

  • 查看 user 表发现新增了一条用户信息,即新开启的事务B 未进行回滚,与预期结果一致


NESTED 和 REQUIRED 的区别

  • REQUIRED 的情况下,调用方存在事务时,则被调用发和调用方使用同一个事务
  • 那么被调用方出现异常时,由于共用同一个事务,所以无论是否 catch 异常,事务都会回滚
  • 而在 NESTTED 情况下,被调用方发生异常时,调用方可以 catch 其异常,这样只有子事务回滚,父事务不回滚

实例理解

  • 我们创建一个 userController 类,并给 addUser 方法加上 REQUIRED 类型的事务
  • 此时的 addUser 方法,将自动创建一个事务A
  • 我们将在 userService 的 add 方法中加入一个 算数异常
  • 为了验证 REQUIRED 的情况下,被调用方出现异常时,由于共用同一个事务,所以无论是否 catch 异常,事务都会回滚
  • 如果不捕获 add 方法抛出的异常 事务A 肯定会进行回滚操作
  • 所以我们此处对算数异常进行捕获,由此来看 事务A 是否还会进行回滚操作
import com.example.demo.entity.User;
import com.example.demo.service.LoggerService;
import com.example.demo.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;@RestController
@RequestMapping("/user2")
public class UserController {@Autowiredprivate UserService userService;@RequestMapping("/add")@Transactional(propagation = Propagation.REQUIRED)public String addUser(User user) {int result = 0;try {
//        调用 userService 的 add 方法result = userService.add(user);}catch (Exception e){e.printStackTrace();}return "add 方法:" + (result == 1 ? "新增用户成功": "新增用户失败");}
}
  • 此处我们给 add 方法加上 REQUIRED 类型的事务
  • 因为 addUser 已经创建了一个事务A,所以此处的 add 方法将会直接加入 事务A 中
  • 此处我们在 add 方法中加入了一个算数异常
import com.example.demo.entity.User;
import com.example.demo.mapper.UserMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;//添加 @Service 注解 代表该类会伴随着 项目的启动而注入到容器中
@Service
public class UserService {@Autowiredprivate UserMapper userMapper;//    新增用户信息@Transactional(propagation = Propagation.REQUIRED)public int add(User user) {int result = userMapper.add(user);int a = 1/0;return result;}
}

运行结果:

  • 在浏览器中输入对应的 URL 来访问 addUser 方法

  • 查看 user 表发现没有新增新用户信息,即事务A进行了回滚操作,与预期结果一致

调整 add 方法的事务传播机制

  • 我们将 add 方法改为  NESTED 类型的事务
  • 因为 addUser 已经创建了一个事务A,所以此处的 add 方法将会在 事务A 中创建一个嵌套事务
import com.example.demo.entity.User;
import com.example.demo.mapper.UserMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;//添加 @Service 注解 代表该类会伴随着 项目的启动而注入到容器中
@Service
public class UserService {@Autowiredprivate UserMapper userMapper;//    新增用户信息@Transactional(propagation = Propagation.NESTED)public int add(User user) {int result = userMapper.add(user);int a = 1/0;return result;}
}

运行结果:

  • 在浏览器中输入对应的 URL 来访问 addUser 方法
  • 此处为了验证 NESTTED 情况下,被调用方发生异常时,调用方可以 catch 其异常,这样只有子事务回滚,父事务不回滚
  • 在浏览器中输入对应的 URL 来访问 addUser 方法

  • 我们可以看到 事务A 未进行回滚操作

  • 查看 user 表发现没有新增新用户信息,即子事务进行了回滚操作,与预期结果一致

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

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

相关文章

蜂窝、无线设备应用 HXG-242+、PVGA-123+、PMA-5452+、PSA-39+、PSA-14+射频放大器(IC器件)

1、HXG-242 射频放大器 IC 无线 LAN&#xff0c;LTE 700MHz 至 2.4GHz&#xff0c;6-SMD 模块 HXG-242&#xff08;符合RoHS规范&#xff09;是一款先进的放大器模块&#xff0c;结合了高动态范围MMIC技术和优化电路&#xff0c;可在聚焦频率范围内提供业界领先的线性度。它采…

创建并测试第一个django项目并解决过程中遇到的问题

Django 是一个高级 Python Web 框架&#xff0c;它鼓励快速开发和简洁、实用的设计。它由经验丰富的开发人员构建&#xff0c;解决了 Web 开发的大部分麻烦&#xff0c;因此您可以专注于编写应用程序&#xff0c;而无需重新发明轮子。它是免费和开源的。 目录 一、django项目 …

Nginx 简单入门操作

前言:之前的文章有些过就不罗嗦了。 Nginx 基础内容 是什么? Nginx 是一个轻量级的 HTTP 服务器,采用事件驱动、异步非阻塞处理方式的服务器,它具有极好的 IO 性能,常用于 HTTP服务器(包含动静分离)、正向代理、反向代理、负载均衡 等等. Nginx 和 Node.js 在很多方…

大语言模型有什么意义?亚马逊训练自己的大语言模型有什么用?

近年来&#xff0c;大语言模型的崭露头角引起了广泛的关注&#xff0c;成为科技领域的一项重要突破。而在这个领域的巅峰之上&#xff0c;亚马逊云科技一直致力于推动人工智能的发展。那么&#xff0c;作为一家全球科技巨头&#xff0c;亚马逊为何会如此注重大语言模型的研发与…

解读 | GPT-4突然“变赖“ 是莫名其妙还是另有玄机

大家好&#xff0c;我是极智视界&#xff0c;欢迎关注我的公众号&#xff0c;获取我的更多前沿科技分享 邀您加入我的知识星球「极智视界」&#xff0c;星球内有超多好玩的项目实战源码和资源下载&#xff0c;链接&#xff1a;https://t.zsxq.com/0aiNxERDq 事情是这样的&#…

项目经理和产品经理哪个更有发展前景?

如果是单看“钱途”的话&#xff0c;如果是在传统行业&#xff0c;可能差不多&#xff1b;如果是在IT行业的话&#xff0c;可能更需要项目经理&#xff1b;互联网行业的话&#xff0c;可能更需要产品经理。 项目经理跟产品经理两个证都挺受市场欢迎的&#xff0c;两个岗位职责…

关东升老师Python著作推荐(由电子工业出版社出版)

前言&#xff1a;关东升老师简单介绍 一个在IT领域摸爬滚打20多年的老程序员、软件架构师、高级培训讲师、IT作家。熟悉Java、Kotlin、Python、iOS、Android、游戏开发、数据库开发与设计、软件架构设计等多种IT技术。参与设计和开发北京市公交一卡通百亿级大型项目&#xff0c…

钓鱼网站域名识别工具dnstwist算法研究

先上一个AI的回答&#xff1a; dnstwist是一种钓鱼网站域名识别工具&#xff0c;可帮助用户识别和检测可能被恶意使用的域名。它通过生成类似的域名变体来模拟攻击者可能使用的钓鱼域名&#xff0c;并提供了一系列有用的功能和信息。 dnstwist能够生成一组类似的域名变体&…

15:00面试,15:06就出来了,问的问题太变态了。。

刚从小厂出来&#xff0c;没想到在另一家公司我又寄了。 在这家公司上班&#xff0c;每天都要加班&#xff0c;但看在钱给的比较多的份上&#xff0c;也就不太计较了。但万万没想到5月一纸通知&#xff0c;所有人不准加班了&#xff0c;不仅加班费没有了&#xff0c;薪资还要降…

有病但合理的 ChatGPT 提示语

ChatGPT 面世一年多了&#xff0c;如何让大模型输出高质量内容&#xff0c;让提示词工程成了一门重要的学科。以下是一些有病但合理的提示词技巧&#xff0c;大部分经过论文证明&#xff0c;有效提高 ChatGPT 输出质量&#xff1a; ​1️⃣ Take a deep breath. 深呼吸 ✨ 作用…

ChatGPT胜过我们人类吗?

引言 人工智能&#xff08;AI&#xff09;一直是众多技术进步背后的驱动力&#xff0c;推动我们走向曾经是科幻小说领域的未来。这些进步的核心引出这样一个深刻的问题&#xff1a;机器能思考吗&#xff1f;这一问题由英国数学家和计算机科学家艾伦图灵&#xff08;Alan Turin…

关于粒子群算法的一些简单尝试

粒子群算法核心思想&#xff1a;&#xff08;鸟 粒子&#xff09; &#xff08;1&#xff09;许多的鸟站在不同的地方&#xff1b; &#xff08;2&#xff09;每一只鸟都有自己寻找食物的初始飞行方向、飞行速度&#xff1b; &#xff08;3&#xff09;这些鸟儿每隔一段时间…

ISP-EE(Edge Enhance)

ISP-EE(Edge Enhance) EE模块在某些ISP主控中叫做sharpness或者sharpen&#xff0c;这些名称指代的模块是同一个&#xff0c;不用再纠结。主要就是在YUV域内弥补成像过程中图像的锐度损失&#xff0c;对边缘和细节进行加强&#xff0c;从而恢复场景本应具有的自然锐度。 锐度…

Linux基础指令(2)

今天我们继续来学我们有关于Linux的指令&#xff0c;今天的指令要比上次多多了。开始我们的学习吧。 man手册 先来看标题&#xff0c;手册我们第一时间想到的就是手册的查阅功能&#xff0c;我们都知道在我们上小学的时候&#xff0c;如果遇到不会的字&#xff0c;我们会通过…

【wvp】无响应sip 日志记录

23-12-11 17:25:18.179 [https-jsse-nio-8970-exec-7] INFO c.g.wvp.vmp.gb28181.transmit.cmd.impl.SIPCommander - 34010200001130000006_34010200001310000006 分配的ZLM为: wvpmediaserver001 [10.30.2.8:30406] 2023-12-11 17:25:18.337 [wvp-9] INFO c.g.w.v.g.t.e.r.i…

【高数:3 无穷小与无穷大】

【高数&#xff1a;3 无穷小与无穷大】 1 无穷小与无穷大2 极限运算法则3 极限存在原则4 趋于无穷小的比较 参考书籍&#xff1a;毕文斌, 毛悦悦. Python漫游数学王国[M]. 北京&#xff1a;清华大学出版社&#xff0c;2022. 1 无穷小与无穷大 无穷大在sympy中用两个字母o表示无…

IvorySQL荣获 OSCHINA「2023 年度优秀开源技术团队」奖

2023 年&#xff0c;OSCHINA 综合平台上各大认证官方技术团队、开源社区帐号年度发表的内容深度及广度、开展各种活动运营影响力等多方面的表现&#xff0c;瀚高股份IvorySQL荣获 OSCHINA颁布的「2023 年度优秀开源技术团队」奖项。未来&#xff0c;IvorySQL将继续为国内开源事…

E4990A 阻抗分析仪,20 Hz 至 10/20/30/50/120 MHz

01 E4990A 阻抗分析仪 20 Hz 至 10/20/30/50/120 MHz 产品综述&#xff1a; E4990A 阻抗分析仪具有 20 Hz 至 120 MHz 的频率范围&#xff0c;可在宽阻抗范围内提供出色的 0.045%&#xff08;典型值&#xff09;基本准确度&#xff0c;并内置 40 V 直流偏置源&#xff0c;适…

计算机科学与技术认识实习【报告】

一、实习目的 此次认识实习主要面对计算机科学与技术专业的同学&#xff0c;了解专业在未来的发展趋势&#xff0c;通过观看公司的介绍视频和技术发展情况招聘信息后的感想和学习体会等多种方式&#xff0c;使我们了解本专业相关领域的发展现状&#xff0c;让我们在校园内课堂上…

C# 数据的保存和提取(.TXT格式)

红色部分的才是最终版 一、将页面内容保存到文件中 第一步 创建Visual的Windows窗体应用,使用的是 第二步 创建几个Label控件、TextBox控件、以及Button按钮,而TextBox控件放入Panel中 第三步 先对写法进行了解,了解保存的语句 StreamWriter sw= new StreamWriter(TXT…