Javaweb之SpringBootWeb案例之事务管理的详细解析

1. 事务管理

1.1 事务回顾

在数据库阶段我们已学习过事务了,我们讲到:

事务是一组操作的集合,它是一个不可分割的工作单位。事务会把所有的操作作为一个整体,一起向数据库提交或者是撤销操作请求。所以这组操作要么同时成功,要么同时失败。

怎么样来控制这组操作,让这组操作同时成功或同时失败呢?此时就要涉及到事务的具体操作了。

事务的操作主要有三步:

  1. 开启事务(一组操作开始前,开启事务):start transaction / begin ;

  2. 提交事务(这组操作全部成功后,提交事务):commit ;

  3. 回滚事务(中间任何一个操作出现异常,回滚事务):rollback ;

1.2 Spring事务管理

1.2.1 案例

简单的回顾了事务的概念以及事务的基本操作之后,接下来我们看一个事务管理案例:解散部门 (解散部门就是删除部门)

需求:当部门解散了不仅需要把部门信息删除了,还需要把该部门下的员工数据也删除了。

步骤:

  • 根据ID删除部门数据

  • 根据部门ID删除该部门下的员工

代码实现:

  1. DeptServiceImpl

@Slf4j
@Service
public class DeptServiceImpl implements DeptService {
    @Autowired
    private DeptMapper deptMapper;
​
    @Autowired
    private EmpMapper empMapper;
​
​
    //根据部门id,删除部门信息及部门下的所有员工
    @Override
    public void delete(Integer id){
        //根据部门id删除部门信息
        deptMapper.deleteById(id);
​
        //删除部门下的所有员工信息
        empMapper.deleteByDeptId(id);   
    }
}
  1. DeptMapper

@Mapper
public interface DeptMapper {
    /**
     * 根据id删除部门信息
     * @param id   部门id
     */
    @Delete("delete from dept where id = #{id}")
    void deleteById(Integer id);
}
  1. EmpMapper

@Mapper
public interface EmpMapper {
​
    //根据部门id删除部门下所有员工
    @Delete("delete from emp where dept_id=#{deptId}")
    public int deleteByDeptId(Integer deptId);
    
}

重启SpringBoot服务,使用postman测试部门删除:

代码正常情况下,dept表和Em表中的数据已删除

修改DeptServiceImpl类中代码,添加可能出现异常的代码:

@Slf4j
@Service
public class DeptServiceImpl implements DeptService {
    @Autowired
    private DeptMapper deptMapper;
​
    @Autowired
    private EmpMapper empMapper;
​
​
    //根据部门id,删除部门信息及部门下的所有员工
    @Override
    public void delete(Integer id){
        //根据部门id删除部门信息
        deptMapper.deleteById(id);
        
        //模拟:异常发生
        int i = 1/0;
​
        //删除部门下的所有员工信息
        empMapper.deleteByDeptId(id);   
    }
}

重启SpringBoot服务,使用postman测试部门删除:

查看数据库表:

  • 删除了2号部门

  • 2号部门下的员工数据没有删除

以上程序出现的问题:即使程序运行抛出了异常,部门依然删除了,但是部门下的员工却没有删除,造成了数据的不一致。

1.2.2 原因分析

原因:

  • 先执行根据id删除部门的操作,这步执行完毕,数据库表 dept 中的数据就已经删除了。

  • 执行 1/0 操作,抛出异常

  • 抛出异常之前,下面所有的代码都不会执行了,根据部门ID删除该部门下的员工,这个操作也不会执行 。

此时就出现问题了,部门删除了,部门下的员工还在,业务操作前后数据不一致。

而要想保证操作前后,数据的一致性,就需要让解散部门中涉及到的两个业务操作,要么全部成功,要么全部失败 。 那我们如何,让这两个操作要么全部成功,要么全部失败呢 ?

那就可以通过事务来实现,因为一个事务中的多个业务操作,要么全部成功,要么全部失败。

此时,我们就需要在delete删除业务功能中添加事务。

在方法运行之前,开启事务,如果方法成功执行,就提交事务,如果方法执行的过程当中出现异常了,就回滚事务。

思考:开发中所有的业务操作,一旦我们要进行控制事务,是不是都是这样的套路?

答案:是的。

所以在spring框架当中就已经把事务控制的代码都已经封装好了,并不需要我们手动实现。我们使用了spring框架,我们只需要通过一个简单的注解@Transactional就搞定了。

1.2.3 Transactional注解

@Transactional作用:就是在当前这个方法执行开始之前来开启事务,方法执行完毕之后提交事务。如果在这个方法执行的过程当中出现了异常,就会进行事务的回滚操作。

@Transactional注解:我们一般会在业务层当中来控制事务,因为在业务层当中,一个业务功能可能会包含多个数据访问的操作。在业务层来控制事务,我们就可以将多个数据访问操作控制在一个事务范围内。

@Transactional注解书写位置:

  • 方法

    • 当前方法交给spring进行事务管理

    • 当前类中所有的方法都交由spring进行事务管理

  • 接口

    • 接口下所有的实现类当中所有的方法都交给spring 进行事务管理

接下来,我们就可以在业务方法delete上加上 @Transactional 来控制事务 。

@Slf4j
@Service
public class DeptServiceImpl implements DeptService {
    @Autowired
    private DeptMapper deptMapper;
​
    @Autowired
    private EmpMapper empMapper;
​
    
    @Override
    @Transactional  //当前方法添加了事务管理
    public void delete(Integer id){
        //根据部门id删除部门信息
        deptMapper.deleteById(id);
        
        //模拟:异常发生
        int i = 1/0;
​
        //删除部门下的所有员工信息
        empMapper.deleteByDeptId(id);   
    }
}

在业务功能上添加@Transactional注解进行事务管理后,我们重启SpringBoot服务,使用postman测试:

添加Spring事务管理后,由于服务端程序引发了异常,所以事务进行回滚。

说明:可以在application.yml配置文件中开启事务管理日志,这样就可以在控制看到和事务相关的日志信息了

#spring事务管理日志
logging:
  level:
    org.springframework.jdbc.support.JdbcTransactionManager: debug

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

第三百一十六回

[tod] 我们在上一章回中介绍了"如何在输入框中处理光标"相关的内容,本章回中将介绍如何添加输入框默认值.闲话休提,让我们一起Talk Flutter吧。 1. 概念介绍 在项目中经常使用输入框获取用户输入的内容,有时候在输入框中反复输入相…

多模态知识图谱:感知与认知的交汇

目录 前言1 多模态知识图谱的概念1.1 感知系统与认知系统的连接1.2 信息形式的整合与融合1.3 全面、多维度的认知基础 2 多模态的作用2.1 模态的知识互补2.2 模态实体消歧2.3 模态语义搜索2.4 知识图谱补全2.5 多模态任务增强 3 多模态知识图谱发展历史3.1 初期模态数据整合3.2…

数据结构——5.4 树、森林

5.4 树、森林 概念 树的存储结构 双亲表示法 孩子表示法 孩子兄弟表示法(二叉树表示法): 二叉树每个结点有三个变量 ① 二叉树结点值:原树结点的值 ② 二叉树左孩子:原树结点的最左孩子 ③ 二叉树右孩子&#xff1a…

【十四】【C++】list 的常见用法

list 的初始化和遍历 /*list的初始化和遍历*/ #if 1 #include <list> #include <vector> #include <iostream> #include<algorithm> using namespace std;void TestList1(){list<int> L1;list<int> L2(10, 5);vector<int> v{1,2,3,4…

实战案例:将已有的 MySQL8.0 单机架构变成主从复制架构

操作步骤 修改 master 主节点 的配置&#xff08; server-id log-bin &#xff09;master 主节点 完全备份&#xff08; mysqldump &#xff09;master 主节点 创建复制用户并授权master 主节点 将完全备份文件拷贝至从节点修改 slave 从节点 的配置&#xff08; server-id rea…

01 MySQL概念

文章目录 数据库MysqlSQL语言 数据库 数据库 &#xff1a; 按照数据一定结构&#xff0c;存储管理数据的仓库。数据库是在数据库管理系统管理和控制下&#xff0c;在一定介质上的数据集合。数据库管理系统 &#xff1a; 管理数据库的软件&#xff0c;用于建立和维护数据库。关…

社区店经营管理新思路:提升业绩的秘诀

作为一名资深的鲜奶吧创业者&#xff0c;我深知在社区经营一家店铺所面临的挑战与机遇。经过5年的探索与实践&#xff0c;我总结出了一套提升社区店业绩的秘诀&#xff0c;今天就和大家分享一下。 一、明确目标客户群体&#xff0c;精准定位 在社区开店&#xff0c;首先要明确…

【Wio Terminal教程】使用LCD屏幕(3)

使用LCD屏幕&#xff08;3&#xff09; 一、加载图片1、安装库2、 图像格式配置3、开始 二、线图1、安装库2、开始 三、直方图1、安装库2、开始 一、加载图片 本节将讲述如何在 Wio Terminal 上从 SD 卡加载并显示图像到 TFT LCD 屏幕。这对于你的设计可能是一个非常有用的实现…

C语言字符串常量

字符串常量 字符串常量在内存中的存储&#xff0c;实质是一个匿名数组匿名数组&#xff0c;同样满足数组两种涵义的规定示例&#xff1a; printf("%d\n", sizeof("abcd")); // 此处 "abcd" 代表整个数组 printf("%p\n", &"…

038 什么是面向对象

面向过程&面向对象 什么是面向对象 现实世界中的事物、类、对象之间的关系 在我们想通过计算机解决一个具体问题的时候&#xff0c;我们可以研究与问题有关事物的共性&#xff0c;比如我在观察了大量的杯子后得出一些结论&#xff1a;杯子都应该有材质、颜色、尺寸、形状这…

Unity 接口、抽象类、具体类对象的配合使用案例

文章目录 示例1&#xff1a;接口&#xff08;Interface&#xff09;示例2&#xff1a;抽象类&#xff08;Abstract Class&#xff09;示例3&#xff1a;结合使用接口与抽象类示例4&#xff1a;多接口实现示例5&#xff1a;抽象类与接口结合 在Unity中使用C#编程时&#xff0c;接…

74HC154D-LED

一、引脚说明 1-11 13-17 &#xff1a;输出端。&#xff08;outputs (active LOW)&#xff09; 12&#xff1a;Gnd电源地 &#xff08;ground (0 V)&#xff09; 18-19&#xff1a;使能输入端、低电平有效 (enable inputs (active LOW)) 20-23&#xff1a;地址输入端 (addr…

计算机网络——04接入网和物理媒体

接入网和物理媒体 接入网络和物理媒体 怎样将端系统和边缘路由器连接&#xff1f; 住宅接入网络单位接入网络&#xff08;学校、公司&#xff09;无线接入网络 住宅接入&#xff1a;modem 将上网数据调制加载到音频信号上&#xff0c;在电话线上传输&#xff0c;在局端将其…

Redis核心技术与实战【学习笔记】 - 30.番外篇:Redis学习资料、运维说明及使用规范建议

1.Redis学习资料 虽然前面已经学习了 Redis 理论和技术点&#xff0c;但是如果想要持续提升自己的技术能力&#xff0c;还是需要不断丰富自己的知识体系。本章&#xff0c;给你推荐几本优秀的书籍&#xff0c;以及拓展知识面的其他资料。 1.1 经典书籍 在学习 Redis 时&…

如何实现视线(目光)的检测与实时跟踪

如何实现视线(目光)的检测与实时跟踪 核心步骤展示说明 找到人脸 检测人脸特征点 根据特征点找到人眼区域 高精度梯度算法检测瞳孔中心 根据眼睛周边特征点计算眼睛中心 瞳孔中心和眼睛中心基于视线模型计算视线方向 视线方向可视化 详细实现与说明&#xff1a; https://stud…

机器学习2--逻辑回归(案列)

糖尿病数据线性回归预测 import numpy as np import pandas as pd import matplotlib.pyplot as plt from sklearn.datasets import load_diabetes diabetesload_diabetes() datadiabetes[data] targetdiabetes[target] feature_namesdiabetes[feature_names] data.shape df …

【知识整理】招人理念、组织结构、招聘

1、个人思考 几个方面&#xff1a; 新人&#xff1a;选、育、用、留 老人&#xff1a;如何甄别&#xff1f; 团队怎么演进&#xff1f; 有没有什么注意事项 怎么做招聘&#xff1f; 2、 他人考虑 重点&#xff1a; 1、从零开始&#xff0c;讲一个搭建团队的流程 2、标…

【MySQL】字符串函数的学习

&#x1f308;个人主页: Aileen_0v0 &#x1f525;热门专栏: 华为鸿蒙系统学习|计算机网络|数据结构与算法 ​&#x1f4ab;个人格言:“没有罗马,那就自己创造罗马~” #mermaid-svg-J7VN4RbrBi51ozap {font-family:"trebuchet ms",verdana,arial,sans-serif;font-siz…

【论文阅读笔记】InstantID : Zero-shot Identity-Preserving Generation in Seconds

InstantID:秒级零样本身份保持生成 理解摘要Introduction贡献 Related WorkText-to-image Diffusion ModelsSubject-driven Image GenerationID Preserving Image Generation Method实验定性实验消融实验与先前方法的对比富有创意的更多任务新视角合成身份插值多身份区域控制合…

探索C语言的内存魔法:动态内存管理解析

✨✨ 欢迎大家来到贝蒂大讲堂✨✨ &#x1f388;&#x1f388;养成好习惯&#xff0c;先赞后看哦~&#x1f388;&#x1f388; 所属专栏&#xff1a;C语言学习 贝蒂的主页&#xff1a;Betty‘s blog 1. 静态开辟内存 通过前面的学习&#xff0c;我们已经掌握了两种开辟内存的方…