事务机制及Spring事务管理

事务概览

事务是一组操作的集合,它是一个不可分割的工作单位。 事务会将所有的操作作为一个整体一起向系统提交或撤销操作请求,换句话说:这些操作要么同时成功、要么同时失败。

具体案例

我们先看一个需求:现在有两张数据库表:员工表emp员工工作经历表emp_expr,现在需要完成新增一个员工的需求,我们需要在员工表中添加员工的基本信息和在员工工作经历表中添加员工的工作经历,这个业务操作就包含了两个操作,根据需求可以先写一个Service方法:

/*** 新增员工* @param emp 员工实体对象*/
@Override
public void addEmp(Emp emp) {// 为新增员工补全属性emp.setCreateTime(LocalDateTime.now());emp.setUpdateTime(LocalDateTime.now());// 新增员工empMapper.insertEmp(emp);// 批量添加员工工作经历Integer empId = emp.getId();List<EmpExpr> exprList = emp.getExprList();// CollectionUtils.isEmpty不但会检查集合是否为空,还会检查集合是否为nullif (!CollectionUtils.isEmpty(exprList)) {exprList.forEach(empExpr -> empExpr.setEmpId(empId));empExprMapper.insertBatch(exprList);}
}

这个Service中的方法先会给Emp员工实体对象补全信息,然后将这些信息添加到数据库表emp中:

/*** 新增员工* @param emp 员工实体对象*/
@Insert("insert into emp(username, name, gender, phone, job, salary, " +"image, entry_date, dept_id, create_time, update_time) values (#{username}, #{name}, #{gender}, #{phone}, " +"#{job}, #{salary}, #{image}, #{entryDate}, #{deptId}, #{createTime}, #{updateTime})")
@Options(useGeneratedKeys = true, keyProperty = "id")
// 添加员工工作经历时需要使用员工id,MyBatis可以设置主键返回,可以返回id主键
void insertEmp(Emp emp);

mapper方法通过@Options注解中的useGeneratedKeys属性将id主键返回(因为Service方法需要使用id主键)

假如该新增员工的工作经历不为空,则会将该员工的工作经历都添加到员工工作经历表emp_expr中。此时,问题就出现了——因为在这个Service方法中包含了两个操作(一个是添加员工、一个是添加员工工作经历),这两个操作都是一个不可分割的工作单位,但假如在添加完员工之后,方法抛出异常,该方法就会结束,员工信息已经成功保存到了数据库中,然而对应的工作经历没有保存!这就导致了数据的不一致性。

事务操作

事务操作主要分为三步操作:

开启事务

需要保证数据一致性的一组操作开始之前,需要先开启事务(start)。

提交事务

如果这一组操作全部执行成功,则可以提交事务(commit)。

回滚事务

假如这一组操作中有任何一个操作失败,都必须回滚事务(rollback) 撤销操作,以保证数据一致性。

事务的操作在生活中的使用是十分广泛的:比如银行转账,如果不使用事务,就会出现转出的账户扣款了,但是转入的账户并没有收到钱,这样的重大BUG,对于这种涉及多个操作的操作,事务管理是十分重要的。

Spring事务管理

通过上述新增员工的案例可以发现:由于没有使用事务机制,所以说出现了员工信息保存了,但是员工工作经历保存失败的问题,从而造成数据不一致的问题。其产生的原因是在Service方法中,保存员工之后方法抛出了异常,导致方法结束,保存工作经历的代码就不会执行了。 为了保证数据的一致性,这两个操作要么全部成功、要么全部失败,此时我们就需要使用事务

由于我们是使用的springboot框架构建的项目,所以说想要使用事务并不需要我们手动实现,Spring框架中已经将事务控制的代码封装完毕,我们只需要使用@Transactional注解即可开启事务控制。

Transactional注解

@Transactional注解会在当前使用的方法上开启事务,方法全部执行完毕之后提交事务,假如该方法在执行过程中出现了异常,那么就会进行事务回滚来撤销本次操作。@Transactional注解可以写在业务层类上,代表该类中的所有方法都交给spring进行事务管理;@Transactional注解写在接口上,代表当前接口的所有实现类中的所有方法都交给spring进行事务管理;@Transactional注解常见于方法上,代表当前方法交给spring进行事务管理。上述案例中,我们就可以在方法上加上@Transactional注解将其交给spring事务管理:

/*** 新增员工* @param emp 员工实体对象*/
@Override
@Transactional // 开启Spring事务机制
public void addEmp(Emp emp) {// 为新增员工补全属性emp.setCreateTime(LocalDateTime.now());emp.setUpdateTime(LocalDateTime.now());// 新增员工empMapper.insertEmp(emp);// 批量添加员工工作经历Integer empId = emp.getId();List<EmpExpr> exprList = emp.getExprList();// CollectionUtils.isEmpty不但会检查集合是否为空,还会检查集合是否为nullif (!CollectionUtils.isEmpty(exprList)) {exprList.forEach(empExpr -> empExpr.setEmpId(empId));empExprMapper.insertBatch(exprList);}
}

我们一般会在业务层当中来控制事务,因为在业务层当中,一个业务功能可能会包含多个数据访问的操作。在业务层来控制事务,我们就可以将多个数据访问操作控制在一个事务范围内。我们还可以在application.properties配置文件中开启事务管理日志:

这样能够更好的使用spring事务管理。

rollbackFor属性

@Transactional注解可以将方法交给spring进行事务管理,但是在默认情况下,只有出现RuntimeException(运行时异常)才会回滚事务,虽然大部分情况下方法的异常都是运行时异常,但是为了以防万一,我们希望方法在出现任何类型的异常时都能回滚事务,此时就需要用到@Transactional注解中的rollbackFor属性来控制回滚了:

@Transactional(rollbackFor = Exception.class)

此时,我们就通过rollbackFor属性指定了方法出现任何异常都将回滚事务。

propagation属性

propagation属性是用于配置事务的传播行为的。事务的传播行为是指:当一个事务方法被另一个事务方法调用时,该事务方法该如何进行事务控制

例如:此时有两个事务方法方法A方法B,两个方法都交给spring进行了事务管理。在A方法运行的时候,首先会开启一个事务,在A方法当中又调用了B方法,但是B方法自身也具有事务,那么B方法在运行的时候,到底是加入到A方法的事务当中来,还是B方法在运行的时候新建一个事务?这就是事务的传播行为。我们可以通过propagation属性控制事务的传播行为:

对于事务传播行为,只需要关注REQUIRED(默认)REQUIRES_NEW即可。大部分情况下,我们只需要使用REQUIRED传播行为即可,但是当我们不希望事务之间互相影响(比如下订单前需要记录日志,但是不论下订单成功与否,都需要成功记录日志)就可以使用REQUIRES_NEW传播行为

事务四大特性

原子性(Atomicity)

原子性是指事务包装的一组SQL是一个不可分割的工作单元事务中的操作要么全部成功、要么全部失败。

一致性(Consistency)

一致性是指一个事务完成之后数据必须处于一致性状态。如果事务执行成功完成,那么数据库的所有变化生效;如果事务执行出现任何错误,那么数据库的所有变化都会回滚(rollback),数据库将返回到原始状态

隔离性(Isolation)

隔离性是指当多用户并发访问数据库时,一个用户的事务不能被其他用户的事务干扰,多个并发的事务之间互相隔离

持久性(Durability)

持久性是指一个事务一但被提交或者回滚,对于数据库的改变是永久性的

事务的四大特性也简称为ACID

总结

当一个方法中包含有多个操作,此时建议开启事务,事务管理可以确保所有的操作要么全部完成、要么全部回滚,可以保证数据的一致性、完整性。对于后端操作数据库是十分重要的技术。

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

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

相关文章

CCLINKIE转ModbusTCP网关,助机器人“掀起”工业智能的“惊涛骇浪”

以下是一个稳联技术CCLINKIE转ModbusTCP网关&#xff08;WL-CCL-MTCP&#xff09;连接三菱PLC与机器人的配置案例&#xff1a;设备与软件准备设备&#xff1a;稳联技术WL-CCL-MTCP网关、三菱FX5UPLC、支持ModbusTCP协议的机器人、网线等。 稳联技术ModbusTCP转CCLINKIE网关&…

python管理工具:conda部署+使用

python管理工具&#xff1a;conda部署使用 一、安装部署 1、 下载 - 官网下载&#xff1a; https://repo.anaconda.com/archive/index.html - wget方式&#xff1a; wget -c https://repo.anaconda.com/archive/Anaconda3-2023.03-1-Linux-x86_64.sh2、 安装 在conda文件的…

python爬虫入门(理论)

python爬虫 学习网站 一、准备 环境搭建 requests beautifulsoup4 selenium 爬虫架构 URL管理器&#xff1a;管理URL&#xff0c;存储已爬取或待爬取的URL 网页下载器&#xff1a;破解网页&#xff0c;进行下载 网页解析器&#xff1a;对网页的HTML样式、连接的URL等进…

windows-本地部署Git仓库-安装Gitea

windows-本地部署Git仓库-安装Gitea 初始化MysQL数据库下载运行后关闭配置服务初始化打开防火墙指定端口入站规则 初始化MysQL数据库 create database gitea character set utf8mb4; 下载 运行后关闭 配置服务 初始化 打开防火墙指定端口入站规则

CV 图像处理基础笔记大全(超全版哦~)!!!

一、图像的数字化表示 像素 数字图像由众多像素组成&#xff0c;是图像的基本构成单位。在灰度图像中&#xff0c;一个像素用一个数值表示其亮度&#xff0c;通常 8 位存储&#xff0c;取值范围 0 - 255&#xff0c;0 为纯黑&#xff0c;255 为纯白。例如&#xff0c;一幅简单的…

Android-目前最稳定和高效的UI适配方案

谈到适配&#xff0c;首先需要介绍几个基本单位&#xff1a; 1、密度无关像素&#xff08;dp&#xff09;&#xff1a; 含义&#xff1a;density-independent pixel&#xff0c;叫dp或dip&#xff0c;与终端上的实际物理像素点无关 单位&#xff1a;dp&#xff0c;可以保证在…

Leetcode 91. 解码方法 动态规划

原题链接&#xff1a;Leetcode 91. 解码方法 自己写的代码&#xff1a; class Solution { public:int numDecodings(string s) {int ns.size();vector<int> dp(n,1);if(s[n-1]0) dp[n-1]0;for(int in-2;i>0;i--){if(s[i]!0){string ts.substr(i,2);int tmpatoi(t.c…

【算法】枚举

枚举 普通枚举1.铺地毯2.回文日期3.扫雷 二进制枚举1.子集2.费解的开关3.Even Parity 顾名思义&#xff0c;就是把所有情况全都罗列出来&#xff0c;然后找出符合题目要求的那一个。因此&#xff0c;枚举是一种纯暴力的算法。一般情况下&#xff0c;枚举策略都是会超时的。此时…

网络分析仪测试S参数

S参数的测试 一&#xff1a;S参数的定义 S参数&#xff08;Scattering Parameters&#xff0c;散射参数&#xff09;是一个表征器件在射频信号激励下的电气行为的工具&#xff0c;它以输入信号、输出信号为元素的矩阵来表现DUT的“传输”和“散射”效应&#xff0c;输入、输出…

联通用户管理系统(一)

#联通用户管理系统&#xff08;一&#xff09; 1.新建项目 如果你是windows的话&#xff0c;界面应该是如下的&#xff1a; 2.创建app python manage.py startapp app01一般情况下&#xff1a;我们是在pycharm的终端中运行上述指令&#xff0c;但是pychrm中为我们提供了工具…

迅为RK3576开发板Android 多屏显示

迅为iTOP-3576开发板采用瑞芯微RK3576高性能、低功耗的应用处理芯片&#xff0c;集成了4个Cortex-A72和4个Cortex-A53核心&#xff0c;以及独立的NEON协处理器。它适用于ARM PC、边缘计算、个人移动互联网设备及其他多媒体产品。 1.1 Android 多屏同显 iTOP-RK3576 开发板支持…

【Axure】配色库

配色库是一个专为设计师和创意工作者打造的在线资源平台&#xff0c;旨在提供丰富的色彩解决方案&#xff0c;帮助用户轻松找到或创造美观和谐的色彩搭配。其中&#xff0c;一个典型的配色库包含了以下几个核心元素&#xff1a; 渐变色&#xff1a;提供多样化的渐变色方案&…

港科夜闻 | 香港科大与微软亚洲研究院签署战略合作备忘录,推动医学健康教育及科研协作...

关注并星标 每周阅读港科夜闻 建立新视野 开启新思维 1、香港科大与微软亚洲研究院签署战略合作备忘录&#xff0c;推动医学健康教育及科研协作。根据备忘录&#xff0c;双方将结合各自于科研领域的优势&#xff0c;携手推动医学健康领域的交流与合作。合作方向将涵盖人才培训、…

机器学习第一道菜(一):线性回归的理论模型

机器学习第一道菜&#xff08;一&#xff09;&#xff1a;线性回归的理论模型 一、问题&#xff1a;千金买笑1.1 散点图1.2 机器学习能搞啥 二、模型的建立2.1 线性回归2.2 回归模型 前面讲了机器学习的“四大绝技”&#xff0c;今天&#xff0c;开始研究第一绝技“回归”&…

【Python】数据容器:列表,元组,字符串,集合字典及通用操作

文章目录 一.序列1.1list列表定义常用操作列表的遍历 1.2tuple元组定义常见操作元组的遍历 1.3str字符串定义常见操作字符串的遍历 1.4序列常用操作——切片 二.set集合定义常见操作集合的遍历 三.dict字典定义常用操作字典的嵌套 *数据容器对比总结四.数据容器的通用操作4.1通…

用 Python 自动化处理日常任务

&#x1f496; 欢迎来到我的博客&#xff01; 非常高兴能在这里与您相遇。在这里&#xff0c;您不仅能获得有趣的技术分享&#xff0c;还能感受到轻松愉快的氛围。无论您是编程新手&#xff0c;还是资深开发者&#xff0c;都能在这里找到属于您的知识宝藏&#xff0c;学习和成长…

java day04-面向对象基础(内存 封装 继承 修饰符 工具类 )

1.对象内存图 1.1 Java 内存分配 1.2 堆和栈 栈:所有局部变量都会在栈内存中创建 局部变量&#xff1a;定义在方法中的变量或者方法声明上的变量 方法执行都会加载到栈中进行 -----------------------------------------------------------------------------------------…

Qt/C++进程间通信:QSharedMemory 使用详解(附演示Demo)

在开发跨进程应用程序时&#xff0c;进程间通信&#xff08;IPC&#xff09;是一个关键问题。Qt 框架提供了多种 IPC 技术&#xff0c;其中 QSharedMemory 是一种高效的共享内存方式&#xff0c;可以实现多个进程之间快速交换数据。本文将详细讲解 QSharedMemory 的概念、用法及…

从前端视角看设计模式之创建型模式篇

设计模式简介 "设计模式"源于GOF&#xff08;四人帮&#xff09;合著出版的《设计模式&#xff1a;可复用的面向对象软件元素》&#xff0c;该书第一次完整科普了软件开发中设计模式的概念&#xff0c;他们提出的设计模式主要是基于以下的面向对象设计原则&#xff…

Pandas数据合并:concat与merge

目录 一、concat方法 1. 基本语法 2. 示例 示例1&#xff1a;按行合并&#xff08;垂直方向&#xff09; 示例2&#xff1a;按列合并&#xff08;水平方向&#xff09; 示例3&#xff1a;使用joininner进行内连接 示例4&#xff1a;处理列名冲突 二、merge方法 1. 基本…