Spring -- 事务

news2024/9/23 16:23:31

Spring中事务的操作分为两类:
(1)编程式事务 – 手动写代码操作事务
(2)声明式事务 – 利用注解开启事务和提交事务

1. 编程式事务

准备Controller


@RestController
@RequestMapping("/user")
public class UserInfoController {
    @Autowired
    private UserInfoService userInfoService;
    @RequestMapping("addUser")
    public String addUser(UserInfo userInfo) {
        userInfoService.insert(userInfo);
        return "SUCCESS";
    }
}

Spring Boot内置了两个对象
DataSourceTransactionManager事务管理器,用来开始事务,提交或回滚事务
TransactionDefinition是事务的属性,在开启事务的时候需要将TransactionDefinition传递进去从而获得一个事务TransactionStatus

先来看没有事务的执行结果:
访问后:
image.png

如果设置了事务:

@RestController
@RequestMapping("/user")
@Slf4j
public class UserInfoController {
    //事务管理器
    @Autowired
    private DataSourceTransactionManager transactionManager;

    //定义事务属性
    @Autowired
    private TransactionDefinition transactionDefinition;


    @Autowired
    private UserInfoService userInfoService;

    @RequestMapping("/addUser")
    public String addUser(UserInfo userInfo) {
        log.info("addUser:{}",userInfo);
        //开启事务
        TransactionStatus transactionStatus = transactionManager.getTransaction(transactionDefinition);

        userInfoService.insert(userInfo);

        //事务提交
        transactionManager.commit(transactionStatus);
        return "SUCCESS";
    }
}

执行结果:
image.png
观察数据库,发现两条数据都有插入:
image.png

如果我们设置了回滚

@RequestMapping("/addUser")
public String addUser(UserInfo userInfo) {
log.info("addUser:{}",userInfo);
//开启事务
TransactionStatus transactionStatus = transactionManager.getTransaction(transactionDefinition);

userInfoService.insert(userInfo);

//事务提交
transactionManager.rollback(transactionStatus);
return "SUCCESS";
}

image.png
对比发现,如果是成功提交,输出的日志是
image.png
如果回滚了,输出的日志是没有这一条信息的,并且数据库也不会更新

但是如果此时我们再次提交事务:
image.png
查看数据库的数据:
image.png
中间空着的id为17的数据就是我们刚刚回滚的操作

2. Spring声明式事务@Transactional

声明式事务的实现需要两步:

2.1 添加依赖

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

2.2 添加@Transactional注解

在需要添加事务的地方加上@Transactional注解即可,无需手动开启事务和提交事务
如果中途发生了没有处理的异常会回滚事务

正常情况:

@RestController
@RequestMapping("/user1")
@Slf4j
public class UserInfoController1 {
    @Autowired
    private UserInfoService userInfoService;

    @Transactional
    @RequestMapping("/addUser1")
    public String addUser(UserInfo userInfo) {
        log.info("addUser:{}",userInfo);
        userInfoService.insert(userInfo);
        return "SUCCESS";
    }
}

image.png

异常情况:

@Transactional
@RequestMapping("/addUser1")
public String addUser(UserInfo userInfo) {
log.info("addUser:{}",userInfo);

userInfoService.insert(userInfo);
int a = 10/0;//出现未处理的异常
return "SUCCESS";
}

image.png
此时会自动回滚,没有提交
但是如果异常在方法内被处理了,就会提交事务

@Transactional
@RequestMapping("/addUser1")
public String addUser(UserInfo userInfo) {
log.info("addUser:{}",userInfo);

userInfoService.insert(userInfo);
try {
    int a = 10/0;
} catch (Exception e) {
    e.printStackTrace();
}
return "SUCCESS";
}

image.png
我们可以在catch里面手动进行回滚事务:

@Transactional
@RequestMapping("/addUser1")
public String addUser(UserInfo userInfo) {
log.info("addUser:{}",userInfo);

userInfoService.insert(userInfo);
try {
    int a = 10/0;
} catch (Exception e) {
    e.printStackTrace();
    TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
}
return "SUCCESS";
}

再次访问:不会提交
image.png

注意:@**Transactional**** **注解可以用来修饰方法或类:

  • 修饰方法时,只有修饰public方法时才生效(修饰其他方法时不会报错,但是不会生效)
  • 修饰类时,类中所有的public方法都会生效
@Transactional
@RequestMapping("/addUser1")
public String addUser(UserInfo userInfo) {
log.info("addUser:{}",userInfo);

userInfoService.insert(userInfo);
try {
    int a = 10/0;
} catch (Exception e) {
    e.printStackTrace();
    TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
}
return "SUCCESS";
}

2.3 @Transactional详解

@Transactional有三个重要的属性:

2.3.1 rollbackFor

@Transactional默认只是在遇到运行时异常以及Error时才会回滚,非运行时异常不会回滚

@Transactional
@RequestMapping("/addUser1")
public String addUser(UserInfo userInfo) throws IOException {
    log.info("addUser:{}",userInfo);

    userInfoService.insert(userInfo);
    if (true) {
        throw new IOException();
    }
    return "SUCCESS";
}

访问:
image.png
事务是会提交的
如果我们需要对所有的异常都回滚,需要配置@Transactional注解当中的rollbackFor属性指定出现何种异常时事务进行回滚

@Transactional(rollbackFor = Exception.class)
@RequestMapping("/addUser1")
public String addUser(UserInfo userInfo) throws IOException {
    log.info("addUser:{}",userInfo);

    userInfoService.insert(userInfo);
    if (true) {
        throw new IOException();
    }
    return "SUCCESS";
}

再次访问:事务不会提交
image.png

2.3.2 事务隔离级别

MySQL事务隔离级别

SQL定义了四种隔离级别:

  1. 读未提交:该隔离级别的事务可以看到其他事务中未提交的数据

其他事务未提交的数据可能会发生回滚,但是该隔离级别的事务可以读到,我们吧该级别读到的数据称为脏数据,这个问题称为脏读

  1. 读已提交:该隔离级别的事务能读取到已经提交事务的数据

该隔离级别不会有脏读的问题,但是由于在事务的执行过程中可以读取到其他事务提交的结果,所以在不同时间相同的sql查询可能会读到不同的结果,这种现象叫做不可重复读

  1. 可重复读:事务不会读到其他事务对已有数据的修改,即使其他事务已经提交,也可以确保

在同一事务多次查询的结果是一致的,但是其他事务新插入的数据,是可以感知到的,这也就引发了幻读问题.可重复读是MySQL默认的事务隔离级别

  1. 串行化:序列化,事务最高的隔离级别,他会强制事务排序,使之不会产生冲突,从而解决

脏读,不可重复读和幻读问题,但是执行效率低,使用场景不多

Spring事务隔离级别

Spring中事务隔离级别有5种

  1. Isolatio.DEFAULT以连接的数据库的事务隔离级别为主
  2. Isolation.READ_UNCOMMITTED:读未提交,对应SQL标准中的读未提交
  3. Isolation.READ_COMMITTED: 读已提交,对应SQL标准中的读已提交
  4. Isolation.REPEATABLE_READ:可重复读.对应SQL标准中的可重复读
  5. Isolation.SERIALIZABLE:串行化,对应SQL标准中的串行化

image.png
Spring中事务隔离级别可以通过@Transactional中的Isolation属性进行设置

@Transactional(rollbackFor = Exception.class,isolation = Isolation.READ_UNCOMMITTED)
@RequestMapping("/addUser1")
public String addUser(UserInfo userInfo) throws IOException {
    log.info("addUser:{}",userInfo);

    userInfoService.insert(userInfo);

    return "SUCCESS";
}

2.3.3 事务传播机制

事务传播机制就是,多个事务之间存在调用关系时,事务是如何在这些方法间进行传播的
比如A方法调用B方法,A执行时,会开启一个事务,B本身也存在一个事务,此时B的事务是加入A的事务,还是创建一个新的事务
这就涉及到了事务传播机制
@Transactional注解支持事务传播机制的设置,通过propagation属性来指定传播行为

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

我们通过代码来演示一下区别:
(1)REQUIRED
image.png
此时由于是REQUIRED,那么三个方法针对的是同一个事务,只要其中有一个出现异常,都会回滚
image.png
image.png
(2)REQUIRES_NEW
image.png
在这种条件下,事务之间是独立的,因此互不影响
image.png
此时user的事务提交了,但是log的事务回滚了

(3)NEVER
image.png
如果存在事务,那就抛出异常
image.png

(4) NESTED
我们先来看看REQUIRED如果方法都执行成功的情况下:
image.png
如果是NESTED,方法都执行成功的情况下:
image.png
image.png
可以发现是等价的,同样是只是开启了一次事务

如果发生了异常
对于REQUIRED方法:

如果是NESTED
image.png
事务都是全部回滚
看似两种好像都是一样的,实际上存在差别
REQUIRED是加入,而NESTED是嵌套
我们通过以下代码就能很好的看出两种的区别:
image.png
对于NESTEDE:
image.png
image.png
但是对于REQUIRED:
image.png
数据库两个表都没有新增数据
可以注意到,在REQUIRED里面,由于是同一个事务,因此不能部分回滚

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

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

相关文章

用Manim创建条形图【BarChart】

BarChart是Manim库中用于创建条形图的函数。它允许用户通过一组值创建一个条形图&#xff0c;其参数可以调整条形的外观和布局。 BarChart(values, bar_namesNone, y_rangeNone, x_lengthNone, y_lengthNone, bar_colors[#003f5c, #58508d, #bc5090, #ff6361, #ffa600],bar_w…

信息安全服务资质CCRC认证需要哪些条件?

CCRC认证是中国信息安全认证中心开展的信息安全服务资质认证&#xff0c;涵盖7个方向&#xff0c;包括安全集成、安全运维、风险评估、应急处理、软件安全开发、灾难备份与恢复、网络安全审计。每个认证方向的资质级别分为一级、二级、三级&#xff0c;一级最高&#xff0c;三级…

网络基础篇~路由、网络类型和相关命令

一、安装Cisco模拟器 功能&#xff1a;Cisco Packet Tracer&#xff0c;是Cisco官方提供的网络模拟器&#xff0c;专门用于教学和学习网络技术。它提供了广泛的Cisco设备模拟&#xff0c;并具有一个直观的界面&#xff0c;可用于创建、配置和模拟网络拓扑。 &#xff08;一&…

基于vue框架的Android共享停车位i00t4(程序+源码+数据库+调试部署+开发环境)系统界面在最后面。

系统程序文件列表 项目功能&#xff1a;用户,车位主,车位出租,车位预约,取消预约 开题报告内容 基于Vue框架的Android共享停车位系统 开题报告 一、研究背景及意义 1.1 研究背景 随着城市化进程的加速&#xff0c;私家车数量急剧增加&#xff0c;停车难问题日益凸显&…

玛雅房产系统源码开发与技术功能解析

引言 随着房地产市场的蓬勃发展&#xff0c;房产管理系统&#xff08;Real Estate Management System, REMS&#xff09;作为提升行业效率、优化资源配置的关键工具&#xff0c;其重要性日益凸显。房产系统源码开发不仅涉及复杂的业务逻辑处理&#xff0c;还融合了先进的软件开…

无人机之热成像篇

一、定义 无人机热成像技术是指将热成像相机安装在无人机云台上&#xff0c;通过无人机的高空飞行能力和云台的稳定性&#xff0c;结合红外热成像技术对目标区域进行非接触式的温度测量和图像采集。该技术利用物体发出的红外辐射来生成图像&#xff0c;通过测量物体表面温度分布…

08、MySQL-事务

目录 1、事务简介 2、事务操作 2.1 方式一 2.2 方式二 3、事务四大特性 4、并发事务问题 5、事务隔离级别 1、事务简介 事务是一组操作的集合&#xff0c;它是一个不可分割的工作单位&#xff0c;事务会把所有的操作作为一个整体一起向系统提交或撤销操作请求&#xff0c…

第27课 Scratch入门篇:放大的数字

放大的数字 故事背景&#xff1a; 舞台上输入 12345&#xff0c;数字竟然能显示很大&#xff0c;奇妙的数字如何显示的&#xff1f; 程序原理&#xff1a; 重点是如何利用克隆的知识&#xff0c;通过角色造型编号来显示具体的数字。 开始编程 1、在角色绘制中&#xff0c;…

Learn ComputeShader 05 Using noise in the shader

首先实现一个简单的噪声效果 实现原理也很简单&#xff0c;只是在每个线程使用随机函数获得一个随机值 float random (float2 pt) {const float a 12.9898;const float b 78.233;const float c 43758.543123;return frac(sin(dot(pt, float2(a, b))) * c ); }[numthreads(8…

STM32-USART时序与寄存器状态分析

一、时序分析 在UART&#xff08;通用异步收发传输&#xff09;通信中&#xff0c;信号线上的状态分为两种&#xff1a;逻辑1&#xff08;高电平&#xff09;和逻辑0&#xff08;低电平&#xff09;。在空闲状态下&#xff0c;数据线应保持逻辑高电平。UART协议中的各个信号位具…

拥抱变革:旗晟智能巡检机器人系统重塑高风险行业巡检模式

随着工业自动化的快速发展&#xff0c;特别是在石油、化工、煤矿等高风险行业中&#xff0c;传统的巡检方式已难以满足现代企业的需求。高频次、全天候、重复的人工巡检不仅效率低下&#xff0c;还面临着人身安全、数据准确性和运营成本等多方面的挑战。针对这些问题&#xff0…

大模型算力基础设施技术趋势、关键挑战与发展路径

文章目录 前言一、大模型技术发展趋势1.1 大语言模型1.2 多模态模型1.3 长序列模型1.4 混合专家模型二、大模型算力基础设施发展问题与挑战2.1 可用算力规模亟需算力利用效率提升2.2 集群性能提升依赖跨尺度、多层次互联三、大模型算力基础设施高质量发展路径总结前言 从大模型…

SpringCloud与SpringBoot之间的关系解析

Spring Cloud和Spring Boot是两个独立的项目&#xff0c;分别用于构建微服务架构和快速构建Java应用程序。它们之间有着密切的关系&#xff0c;可以相互配合使用。 Spring Boot简介 Spring Boot是一个用于快速构建Java应用程序的框架。它简化了Spring应用程序的开发过程&#x…

Redis,MongoDB,Memcached未授权访问漏洞(及其修复方法)

一. Redis Redis 默认情况下&#xff0c;会绑定在 0.0.0.0:6379 &#xff0c;如果没有进⾏采⽤相关的策略&#xff0c;⽐如添加防 ⽕墙规则避免其他⾮信任来源 ip 访问等&#xff0c;这样将会将 Redis 服务暴露到公⽹上&#xff0c;如果在没有设 置密码认证&#xff08;⼀般为空…

【haproxy】haproxy基本配置信息

一、负载均衡 LB&#xff1a; LoadBalancing&#xff08;负载均衡&#xff09;由多个主机组成&#xff0c;每个主机只承担一部分访问 负载均衡:Load Balance,简称LB&#xff0c;是一种服务或基于硬件设备等实现的高可用反向代理技术&#xff0c;负载均衡将特定的业务(web服务、…

新书速览|Python数据可视化:科技图表绘制(送书)

《Python数据可视化:科技图表绘制》 本书内容 《Python数据可视化:科技图表绘制》结合编者多年的数据分析与科研绘图经验&#xff0c;详细讲解Python语言及包括Matplotlib在内的多种可视化包在数据分析与科研图表制作中的使用方法与技巧。《Python数据可视化:科技图表绘制》分为…

WWDg 正点原子版

窗口看门狗 超时时间计算如下 f1系列&#xff0c;wwdg的时钟源频率是36mhz&#xff0c;时钟频率➗&#xff08;4096*分频系数&#xff09;就是得到实际的频率&#xff0c;也就是一秒钟能计数好多次&#xff0c;那么频率的倒数也就是计数一次需要的时间&#xff0c;所以频率的倒…

【Linux】阻塞信号|信号原理

常见的信号术语 信号递达&#xff08;Delivery&#xff09;: 信号实际被执行处理的过程;&#xff08;当一个信号被递达给进程时&#xff0c;该信号的处理动作已经开始执行实际执行信号的处理动作&#xff09;&#xff1b; 信号未决&#xff08;Pending&#xff09;: 信号从产生…

快速上手Spring Boot

快速上手Spring Boot (qq.com)

凡图公益行:以爱之名,凡图家庭教育专家入户指导,引领残疾儿童勇敢启航 !

凡图公益行&#xff1a;以爱之名&#xff0c;凡图家庭教育专家入户指导&#xff0c;引领残疾儿童勇敢启航 &#xff01; 在社会的各个角落&#xff0c;有一群特殊的孩子。 他们因身体的局限承受着常人难以想象的挑战。 这些挑战不仅体现在日常生活的琐碎之中&#xff0c;更深…