Spring事务回滚在系统中的应用

news2025/7/24 4:38:15

以文章发布为例,介绍Spring事务回滚在系统中的应用

事务回滚的核心概念

事务回滚是数据库管理系统中的关键机制,它确保数据库操作要么全部成功,要么全部失败。在Spring框架中,我们可以通过@Transactional注解轻松实现事务管理。

事务的ACID特性

  • 原子性(Atomicity):操作不可分割,要么全部完成,要么全部不执行
  • 一致性(Consistency):事务前后数据库状态保持一致
  • 隔离性(Isolation):并发事务互不干扰
  • 持久性(Durability):事务完成后结果永久保存

文章发布系统的事务应用

在我们的文章发布系统中,存在两种业务场景:

  1. 正式发布:所有操作(主表、文件、白名单)必须全部成功
  2. 草稿保存:主表必须成功,其他操作尽量完成但不强制

事务控制实现代码

@Transactional(rollbackFor = Exception.class)
public RestResponse publishArticle(PublishArticleRequest request) {
    boolean isDraft = request.getIsDraft() == 2;
    
    try {
        // 设置默认值
        request.setIsDelete(1);
        // ...其他默认值设置
        
        // 保存文章主表
        int articleId = userArticlesMapper.publishArticle(request);
        
        // 尝试保存附加数据
        saveAdditionalData(request, articleId, isDraft);
        
        return RestResponse.success(isDraft ? "草稿保存成功" : "发布成功");
    } catch (Exception e) {
        // 手动标记回滚
        TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
        return RestResponse.fail(isDraft ? "草稿保存失败" : "发布失败");
    }
}

private void saveAdditionalData(PublishArticleRequest request, int articleId, boolean isDraft) {
    try {
        // 1. 保存可见白名单
        if (request.getWatchPermission() == 4) {
            // ...构建白名单数据
            userArticlesMapper.publishWatchPermissionnList(watchList);
        }
        
        // 2. 保存评价白名单
        if (request.getEvaluatePermission() == 4) {
            // ...构建评价白名单数据
            userArticlesMapper.publishEvaluatePermissionnList(evaluateList);
        }
        
        // 3. 批量保存文件(性能优化关键)
        if (request.getFiles() != null && !request.getFiles().isEmpty()) {
            List<BaseUserArticlesFiles> fileList = request.getFiles().stream()
                .map(fileUrl -> new BaseUserArticlesFiles(articleId, fileUrl))
                .collect(Collectors.toList());
            userArticlesMapper.batchInsertFiles(fileList);
        }
    } catch (Exception e) {
        if (isDraft) {
            // 草稿模式:只记录日志,不抛出异常
            log.warn("草稿附加数据保存失败(不影响主表)", e);
        } else {
            // 发布模式:抛出异常触发事务回滚
            throw e;
        }
    }
}

实体类优化支持批量操作

@Data
public class BaseUserArticlesFiles {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Integer id;
    
    private Integer userArticlesId;
    private Integer isDelete = 1; // 默认值
    private String fileUrl;

    // 支持批量插入的构造方法
    public BaseUserArticlesFiles(Integer userArticlesId, String fileUrl) {
        this.userArticlesId = userArticlesId;
        this.fileUrl = fileUrl;
    }
}

MyBatis批量插入实现

<!-- 批量插入文件 -->
<insert id="batchInsertFiles" parameterType="list">
    INSERT INTO base_user_articles_files 
        (user_articles_id, file_url, is_delete)
    VALUES
    <foreach collection="fileList" item="file" separator=",">
        (#{file.userArticlesId}, #{file.fileUrl}, #{file.isDelete})
    </foreach>
</insert>

事务回滚的工作原理

在这里插入图片描述

性能优化:批量操作

在文件保存场景中,使用批量插入显著提升性能:

// 普通单条插入(N+1问题)
for (String file : files) {
    mapper.insertFile(new File(articleId, file));
}

// 批量插入(高效)
List<File> fileList = files.stream()
    .map(file -> new File(articleId, file))
    .collect(Collectors.toList());
mapper.batchInsertFiles(fileList);

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

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

相关文章

ASP.NET Core使用Quartz部署到IIS资源自动被回收解决方案

iis自动回收的原因 回收机制默认配置&#xff0c;间隔时间是1740分钟&#xff0c;意思是&#xff1a;默认情况下每1740分钟(29小时)回收一次&#xff0c;定期检查应用程序池中的工作进程&#xff0c;并终止那些已经存在很长时间或已经使用了太多资源的工作进程 进程模型默认配…

调用.net DLL让CANoe自动识别串口号

1.前言 CANoe9.0用CAPL控制数控电源_canoe读取程控电源电流值-CSDN博客 之前做CAPL通过串口控制数控电源&#xff0c;存在一个缺点&#xff1a;更换电脑需要改串口号 CSDN上有类似的博客&#xff0c;不过要收费&#xff0c;本文根据VID和PID来自动获取串口号&#xff0c;代码…

算法(蓝桥杯学习C/C++版)

up: 溶金落梧桐 溶金落梧桐的个人空间-溶金落梧桐个人主页-哔哩哔哩视频 蓝桥杯三十天冲刺系列 BV18eQkY3EtP 网站&#xff1a; OI Wiki OI Wiki - OI Wiki 注意 比赛时&#xff0c;devc勾选c11&#xff08;必看&#xff09; 必须勾选c11一共有两个方法&#xff0c;任用…

Docker镜像无法拉取问题解决办法

最近再学习RabbitMQ&#xff0c;需要从Docker镜像中拉取rabbitMQ&#xff0c;但是下拉失败 总的来说就是无法和docker镜像远程仓库建立连接 我又去尝试ping docker.io发现根本没有反应&#xff0c;还是无法连接找了许多办法还是没有办法解决&#xff0c;最后才发现是镜像问题&a…

ZephyrOS 嵌入式开发Black Pill V1.2之Debug调试器

版本和环境信息如下&#xff1a; PC平台&#xff1a; Windows 11 专业版 Zephyr开发环境&#xff1a;v4.1.0 Windows 下搭建 Zephyr 开发环境 WeAct BlackPill V1.2开发板&#xff1a; WeAct STM32F411CEU6 BlackPill 核心板 Debug调试器&#xff1a; ST-LINK V2: ST-LINK V2 S…

服务器磁盘空间被Docker容器日志占满处理方法

事发场景&#xff1a; 原本正常的服务停止运行了&#xff0c;查看时MQTT服务链接失败&#xff0c;查看对应的容器服务发现是EMQX镜像停止运行了&#xff0c;重启也是也报错无法正常运行&#xff0c;报错如下图&#xff1a; 报错日志中连续出现两个"no space left on devi…

c++学习-this指针

1.基本概念 非静态成员函数都会默认传递this指针&#xff08;静态成员函数属于类本身&#xff0c;不属于某个实例对象&#xff09;&#xff0c;方便访问对象对类成员变量和 成员函数。 2.基本使用 编译器实际处理类成员函数&#xff0c;this是第一个隐藏的参数&#xff0c;类…

交易所系统攻坚:高并发撮合引擎与合规化金融架构设计

交易所系统攻坚&#xff1a;高并发撮合引擎与合规化金融架构设计 ——2025年数字资产交易平台的性能与合规双轮驱动 一、高并发撮合引擎&#xff1a;从微秒级延迟到百万TPS 核心架构设计 订单簿优化&#xff1a;数据结构创新&#xff1a;基于红黑树与链表混合存储&#xff0c…

OpenCV计算机视觉实战(10)——形态学操作详解

OpenCV计算机视觉实战&#xff08;10&#xff09;——形态学操作详解 0. 前言1. 腐蚀与膨胀1.1 为什么要做腐蚀与膨胀1.2 OpenCV 实现 2. 开运算与闭运算2.1 开运算与闭运算原理2.2 OpenCV 实现 3. 形态学梯度与骨架提取3.1 形态学梯度3.2 骨架提取 小结系列链接 0. 前言 形态…

[论文阅读] 人工智能 | 利用负信号蒸馏:用REDI框架提升LLM推理能力

【论文速读】利用负信号蒸馏&#xff1a;用REDI框架提升LLM推理能力 论文信息 arXiv:2505.24850 cs.LG cs.AI cs.CL Harnessing Negative Signals: Reinforcement Distillation from Teacher Data for LLM Reasoning Authors: Shuyao Xu, Cheng Peng, Jiangxuan Long, Weidi…

基于 NXP + FPGA+Debian 高可靠性工业控制器解决方案

在工业系统开发中&#xff0c;**“稳定”**往往比“先进”更重要。设备一旦部署&#xff0c;生命周期动辄 5~10 年&#xff0c;系统重启或异常恢复成本高昂。 这时候&#xff0c;一套“值得托付”的软硬件组合&#xff0c;就显得尤为关键。 ✅ NXP —— 提供稳定、长期供货的工…

垂起固定翼无人机应用及技术分析

一、主要应用行业 1. 能源基础设施巡检 电力巡检&#xff1a;适用于超高压输电线路通道的快速巡查&#xff0c;实时回传数据提升智能运检效率。 油田管道监测&#xff1a;利用长航时特性&#xff08;1.5-2小时&#xff09;对大范围管道进行隐患排查&#xff0c;减少人力巡…

vite配置@别名,以及如何让IDE智能提示路经

1.配置路径(vite.config.js) // vite.config.js import { defineConfig } from "vite"; import vue from "vitejs/plugin-vue"; import path from "path";// https://vite.dev/config/ export default defineConfig({server: {port: 8080,},plu…

【Linux】LInux下第一个程序:进度条

前言&#xff1a; 在前面的文章中我们学习了LInux的基础指令 【Linux】初见&#xff0c;基础指令-CSDN博客【Linux】初见&#xff0c;基础指令&#xff08;续&#xff09;-CSDN博客 学习了vim编辑器【Linux】vim编辑器_linux vim insert-CSDN博客 学习了gcc/g【Linux】编译器gc…

RPA+AI:自动化办公机器人开发指南

RPAAI&#xff1a;自动化办公机器人开发指南 系统化学习人工智能网站&#xff08;收藏&#xff09;&#xff1a;https://www.captainbed.cn/flu 文章目录 RPAAI&#xff1a;自动化办公机器人开发指南摘要引言技术融合路径1. 传感器层&#xff1a;多模态数据接入2. 决策层&…

计算矩阵A和B的乘积

根据矩阵乘法规则&#xff0c;编程计算矩阵的乘积。函数fix_prod_ele()是基本方法编写&#xff0c;函数fix_prod_opt()是优化方法编写。 程序代码 #define N 3 #define M 4 typedef int fix_matrix1[N][M]; typedef int fix_matrix2[M][N]; int fix_prod_ele(f…

Houdini POP入门学习05 - 物理属性

接下来随着教程学习碰撞部分&#xff0c;当粒子较为复杂或者下载了一些粒子模板进行修改时&#xff0c;会遇到一些较奇怪问题&#xff0c;如粒子穿透等&#xff0c;这些问题实际上可以通过调节参数解决。 hip资源文件&#xff1a;https://download.csdn.net/download/grayrail…

每日Prompt:双重曝光

提示词 新中式&#xff0c;这幅图像将人体头像轮廓与山水中式建筑融为一体&#xff0c;双重曝光&#xff0c;体现了反思、内心平静以及人与自然相互联系的主题&#xff0c;靛蓝&#xff0c;水墨画&#xff0c;晕染&#xff0c;极简

【LLM】多智能体系统 Why Do Multi-Agent LLM Systems Fail?

note 构建一个成功的 MAS&#xff0c;不仅仅是提升底层 LLM 的智能那么简单&#xff0c;它更像是在构建一个组织。如果组织结构、沟通协议、权责分配、质量控制流程设计不当&#xff0c;即使每个成员&#xff08;智能体&#xff09;都很“聪明”&#xff0c;整个系统也可能像一…

CSS 定位:原理 + 场景 + 示例全解析

一. 什么是CSS定位? CSS中的position属性用于设置元素的定位方式,它决定了元素在页面中的"定位行为" 为什么需要定位? 常规布局(如 display: block)适用于主结构 定位适用于浮动按钮,弹出层,粘性标题等场景帮助我们精确控制元素在页面中的位置 二. 定位类型全…