当前位置: 首页 > news >正文

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

相关文章:

  • 使用C++从零开始,自己写一个MiniWeb
  • 贪心算法之找零钱
  • openJudge | 距离排序 C语言
  • OCP使用web console创建和构建应用
  • 设计模式理解:单例模式+工厂模式+建设者模式+原型模式
  • macbook电脑如何永久删除app软件?
  • 使用C#快速创建一个非常实用的桌面应用程序
  • 设计模式-建造者模式Builder
  • 【开源】SpringBoot框架开发桃花峪滑雪场租赁系统
  • Linux cksum命令教程:如何使用cksum命令检查文件完整性(附实例详解和注意事项)
  • 选择大语言模型:2024 年开源 LLM 入门指南
  • 【电路笔记】-并联电感
  • STM32自学☞PWM驱动舵机(按键控制)
  • ubuntu快速安装miniconda
  • Python学习之路-爬虫提高:常见的反爬手段和解决思路
  • 【刷算法】从上往下打印二叉树
  • axios 和 cookie 的那些事
  • Docker 笔记(1):介绍、镜像、容器及其基本操作
  • golang中接口赋值与方法集
  • JavaScript DOM 10 - 滚动
  • leetcode378. Kth Smallest Element in a Sorted Matrix
  • spring + angular 实现导出excel
  • spring学习第二天
  • swift基础之_对象 实例方法 对象方法。
  • Vue全家桶实现一个Web App
  • 百度贴吧爬虫node+vue baidu_tieba_crawler
  • 聊聊flink的TableFactory
  • 聊聊springcloud的EurekaClientAutoConfiguration
  • 深入体验bash on windows,在windows上搭建原生的linux开发环境,酷!
  • 小程序开发之路(一)
  • 小李飞刀:SQL题目刷起来!
  • 直播平台建设千万不要忘记流媒体服务器的存在 ...
  • ​人工智能书单(数学基础篇)
  • !! 2.对十份论文和报告中的关于OpenCV和Android NDK开发的总结
  • # 数论-逆元
  • (10)工业界推荐系统-小红书推荐场景及内部实践【排序模型的特征】
  • (51单片机)第五章-A/D和D/A工作原理-A/D
  • (多级缓存)缓存同步
  • (二)springcloud实战之config配置中心
  • (附源码)springboot炼糖厂地磅全自动控制系统 毕业设计 341357
  • (免费领源码)Java#Springboot#mysql农产品销售管理系统47627-计算机毕业设计项目选题推荐
  • (四)Android布局类型(线性布局LinearLayout)
  • (五)c52学习之旅-静态数码管
  • (一)Linux+Windows下安装ffmpeg
  • .NET 4.0网络开发入门之旅-- 我在“网” 中央(下)
  • .net6解除文件上传限制。Multipart body length limit 16384 exceeded
  • .NET的数据绑定
  • .net开发引用程序集提示没有强名称的解决办法
  • .net开源工作流引擎ccflow表单数据返回值Pop分组模式和表格模式对比
  • @Transactional注解下,循环取序列的值,但得到的值都相同的问题
  • [ C++ ] STL---string类的使用指南
  • [ Linux ] git工具的基本使用(仓库的构建,提交)
  • [3D游戏开发实践] Cocos Cyberpunk 源码解读-高中低端机性能适配策略
  • [Android]Tool-Systrace
  • [Android]通过PhoneLookup读取所有电话号码