Javaweb之SpringBootWeb案例之propagation属性案例演示的详细解析

案例

接下来我们就通过一个案例来演示下事务传播行为propagation属性的使用。

需求:解散部门时需要记录操作日志

由于解散部门是一个非常重要而且非常危险的操作,所以在业务当中要求每一次执行解散部门的操作都需要留下痕迹,就是要记录操作日志。而且还要求无论是执行成功了还是执行失败了,都需要留下痕迹。

步骤:

  1. 执行解散部门的业务:先删除部门,再删除部门下的员工(前面已实现)

  2. 记录解散部门的日志,到日志表(未实现)

准备工作:

  1. 创建数据库表 dept_log 日志表:

create table dept_log(id int auto_increment comment '主键ID' primary key,create_time datetime null comment '操作时间',description varchar(300) null comment '操作描述'
)comment '部门操作日志表';
  1. 引入资料中提供的实体类:DeptLog

@Data
@NoArgsConstructor
@AllArgsConstructor
public class DeptLog {private Integer id;private LocalDateTime createTime;private String description;
}
  1. 引入资料中提供的Mapper接口:DeptLogMapper

@Mapper
public interface DeptLogMapper {
​@Insert("insert into dept_log(create_time,description) values(#{createTime},#{description})")void insert(DeptLog log);
​
}
  1. 引入资料中提供的业务接口:DeptLogService

public interface DeptLogService {void insert(DeptLog deptLog);
}
  1. 引入资料中提供的业务实现类:DeptLogServiceImpl

@Service
public class DeptLogServiceImpl implements DeptLogService {
​@Autowiredprivate DeptLogMapper deptLogMapper;
​@Transactional //事务传播行为:有事务就加入、没有事务就新建事务@Overridepublic void insert(DeptLog deptLog) {deptLogMapper.insert(deptLog);}
}
​

代码实现:

业务实现类:DeptServiceImpl

@Slf4j
@Service
//@Transactional //当前业务实现类中的所有的方法,都添加了spring事务管理机制
public class DeptServiceImpl implements DeptService {@Autowiredprivate DeptMapper deptMapper;@Autowiredprivate EmpMapper empMapper;
​@Autowiredprivate DeptLogService deptLogService;
​
​//根据部门id,删除部门信息及部门下的所有员工@Override@Log@Transactional(rollbackFor = Exception.class) public void delete(Integer id) throws Exception {try {//根据部门id删除部门信息deptMapper.deleteById(id);//模拟:异常if(true){throw new Exception("出现异常了~~~");}//删除部门下的所有员工信息empMapper.deleteByDeptId(id);}finally {//不论是否有异常,最终都要执行的代码:记录日志DeptLog deptLog = new DeptLog();deptLog.setCreateTime(LocalDateTime.now());deptLog.setDescription("执行了解散部门的操作,此时解散的是"+id+"号部门");//调用其他业务类中的方法deptLogService.insert(deptLog);}}//省略其他代码...
}

测试:

重新启动SpringBoot服务,测试删除3号部门后会发生什么?

  • 执行了删除3号部门操作

  • 执行了插入部门日志操作

  • 程序发生Exception异常

  • 执行事务回滚(删除、插入操作因为在一个事务范围内,两个操作都会被回滚)

然后在dept_log表中没有记录日志数据

原因分析:

接下来我们就需要来分析一下具体是什么原因导致的日志没有成功的记录。

  • 在执行delete操作时开启了一个事务

  • 当执行insert操作时,insert设置的事务传播行是默认值REQUIRED,表示有事务就加入,没有则新建事务

  • 此时:delete和insert操作使用了同一个事务,同一个事务中的多个操作,要么同时成功,要么同时失败,所以当异常发生时进行事务回滚,就会回滚delete和insert操作

解决方案:

在DeptLogServiceImpl类中insert方法上,添加@Transactional(propagation = Propagation.REQUIRES_NEW)

Propagation.REQUIRES_NEW :不论是否有事务,都创建新事务 ,运行在一个独立的事务中。

@Service
public class DeptLogServiceImpl implements DeptLogService {
​@Autowiredprivate DeptLogMapper deptLogMapper;
​@Transactional(propagation = Propagation.REQUIRES_NEW)//事务传播行为:不论是否有事务,都新建事务@Overridepublic void insert(DeptLog deptLog) {deptLogMapper.insert(deptLog);}
}

重启SpringBoot服务,再次测试删除3号部门:

那此时,DeptServiceImpl中的delete方法运行时,会开启一个事务。 当调用 deptLogService.insert(deptLog) 时,也会创建一个新的事务,那此时,当insert方法运行完毕之后,事务就已经提交了。 即使外部的事务出现异常,内部已经提交的事务,也不会回滚了,因为是两个独立的事务。

到此事务传播行为已演示完成,事务的传播行为我们只需要掌握两个:REQUIRED、REQUIRES_NEW。

  • REQUIRED :大部分情况下都是用该传播行为即可。

  • REQUIRES_NEW :当我们不希望事务之间相互影响时,可以使用该传播行为。比如:下订单前需要记录日志,不论订单保存成功与否,都需要保证日志记录能够记录成功。

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

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

相关文章

2024beginCTF-Crypto 复现

fake_N 题目: from Crypto.Util.number import * from secret import flagdef fakeN_list():puzzle_list []for i in range(15):r getPrime(32)puzzle_list.append(r)p getPrime(32)q getPrime(32)com p*qpuzzle_list.append(com)return puzzle_listdef encr…

洛谷数组P1319压缩技术

做题思路: 这里表示输入的第一个数字N为N*N的方阵,后面的数字表示连续输入几个1或者0,定义result表示实际输出的数字0或1(result输出0或1,可以用绝对值abs我们初始化result为0,我们将它-1后再取绝对值就可以…

C++ //练习 6.23 参考本节介绍的几个print函数,根据理解编写你自己的版本。依次调用每个函数使其输入下面定义的i和j

C Primer(第5版) 练习 6.23 练习 6.23 参考本节介绍的几个print函数,根据理解编写你自己的版本。依次调用每个函数使其输入下面定义的i和j: int i 0, j[2] {0, 1};环境:Linux Ubuntu(云服务器&#xff…

RK3588平台开发系列讲解(视频篇)RKMedia 数据流向

文章目录 一、 获取RKMedia模块通道中的数据二、RKMedia的数据源和接收者三、模块通道绑定API调用 沉淀、分享、成长,让自己和他人都能有所收获!😄 📢RKMedia是RK提供的一种多媒体处理方案,可实现音视频捕获、音视频输…

LeetCode二叉树的垂序遍历

题目描述 给你二叉树的根结点 root ,请你设计算法计算二叉树的 垂序遍历 序列。 对位于 (row, col) 的每个结点而言,其左右子结点分别位于 (row 1, col - 1) 和 (row 1, col 1) 。树的根结点位于 (0, 0) 。 二叉树的 垂序遍历 从最左边的列开始直到…

python 经典老人言

python 经典老人言 import tkinter as tkclass FlipBook:def __init__(self, master):self.master master master.title("经 典 老 人 言")self.pages ["经 典 老 人 言","求学无笨者,努力就成功","读 书 百 遍&am…

Golang中的fmt包:格式化输入输出的利器

Golang中的fmt包:格式化输入输出的利器 在软件开发的世界里,fmt包就像是一位忠实的伙伴,始终陪伴着开发人员。它简化了格式化输入输出的过程,让打印和扫描数据变得轻松自如。无论是向控制台输出简单的消息,还是处理复杂…

LeetCode、1143. 最长公共子序列【中等,二维DP】

文章目录 前言LeetCode、1143. 最长公共子序列【中等,二维DP】题目链接与分类思路2022年暑假学习思路及题解二维DP解决 资料获取 前言 博主介绍:✌目前全网粉丝2W,csdn博客专家、Java领域优质创作者,博客之星、阿里云平台优质作者…

Python学习之路-爬虫提高:scrapy基础

Python学习之路-爬虫提高:scrapy基础 为什么要学习scrapy 通过前面的学习,我们已经能够解决90%的爬虫问题了,那么scrapy是为了解决剩下的10%的问题么,不是,scrapy框架能够让我们的爬虫效率更高 什么是scrapy Scrapy是一个为了…

npm报错之package-lock.json found. 问题和淘宝镜像源过期问题

1、package-lock.json found. 问题的解决 在执行yarn add react-transition-group -S 安装react-transition-group时出现package-lock.json found. Your project contains lock files generated by tools other than Yarn. It is advised not to mix package managers in orde…

国内国外最好的数据恢复软件评测,哪种数据恢复软件最有效?

随着数字和商业格局在多个领域不断发展,变得更加依赖数据,威胁数据的努力也同样存在。 计算机病毒、勒索软件和恶意软件是导致数据丢失的主要威胁,可能会让您的组织陷入停机或严重影响您的工作效率。而解决这个问题的方法就是数据恢复。 什么…

Java网络编程 单向通信

目录 网络编程实例创建客户端创建服务端测试 网络编程 Java的网络编程是Java编程语言中用于实现网络通信的一组API和工具。通过Java的网络编程,开发人员可以在Java应用程序中实现客户端和服务器之间的通信,从而构建各种网络应用。 以下是Java网络编程的…