@Transactional事務注解的批量回滾機制

關鍵機制說明:

1.??事務注解生效??:

@Transactional(rollbackFor = Exception.class)

@Override
@Transactional(rollbackFor = Exception.class)
public Boolean saveUser(UserDTO userDto) {SysUser sysUser = new SysUser();BeanUtils.copyProperties(userDto, sysUser);sysUser.setDelFlag(CommonConstants.STATUS_NORMAL);sysUser.setPassword(ENCODER.encode(userDto.getPassword()));baseMapper.insert(sysUser);List<SysUserRole> userRoleList = userDto.getRole().stream().map(roleId -> {SysUserRole userRole = new SysUserRole();userRole.setUserId(sysUser.getUserId());userRole.setRoleId(roleId);return userRole;}).collect(Collectors.toList());return sysUserRoleService.saveBatch(userRoleList);
}
  • 該注解將整個方法納入??同一個數據庫事務??。
  • rollbackFor = Exception.class?指定了所有異常(包括?RuntimeException?和受檢異常)都會觸發回滾。
??2.事務回滾邏輯??:
  • 事務內任何操作拋出異常(如數據庫約束沖突、網絡中斷等),整個事務會回滾到方法開始前的狀態。
  • 本方法包含兩個數據庫操作:
    • baseMapper.insert(sysUser):插入用戶記錄
    • sysUserRoleService.saveBatch(userRoleList):批量插入用戶角色關聯記錄
  • ??這兩個操作共享同一個事務??,任何一步失敗都會回滾所有操作。
???3.批量保存的異常行為??:
  • MyBatis-Plus 的?saveBatch()?在默認配置下,如果批量操作中??任意一條數據失敗??,??會拋出異常??(如?DataAccessException)。
  • 此時事務管理器會捕獲異常,并回滾整個事務。

需要注意的細節:

  • ??批量操作實際執行方式??:

    • saveBatch()?默認可能通過 ??分批提交 SQL??(如每批 1000 條)執行。但如果某條數據失敗(如唯一鍵沖突),MyBatis-Plus 會拋出異常,觸發回滾,??已插入的本批次數據也會回滾??。
  • ??自調用問題??:

    • 如果該方法被??同一個類中的其他方法直接調用??(而非通過 Spring 代理對象),@Transactional?會失效。確保通過 Spring 容器管理的方法調用。

驗證場景:

// 模擬批量保存時部分數據失敗(如角色ID不存在)
List<SysUserRole> userRoleList = Arrays.asList(
new SysUserRole(sysUser.getUserId(), 1), // 有效數據
new SysUserRole(sysUser.getUserId(), 999) // 無效數據(觸發外鍵沖突)
);

sysUserRoleService.saveBatch(userRoleList); // 失敗拋出異常

  • ??結果??:sysUser?的插入操作也會被回滾,數據庫無新增用戶和角色關聯記錄。

總結:

只要批量保存中有一條記錄失敗拋出異常,整個事務回滾,確保用戶數據和關聯角色數據的一致性??。這是事務 ACID 特性(原子性)的直接體現。


如果將上面的mybatisplus提供的saveBatch批量增加改成自己用for循環單條增加數據,事務還起作用嗎?

答案:

??事務仍然會起作用,而且效果相同!?? 只要循環中的任意一次單條保存失敗,??整個事務都會回滾??(包括?baseMapper.insert(sysUser)?插入的用戶記錄和之前成功的角色記錄)。

詳細分析:

1. 修改后的代碼示例(使用循環單條保存):
@Override
@Transactional(rollbackFor = Exception.class)
public Boolean saveUser(UserDTO userDto) {// 插入用戶記錄SysUser sysUser = new SysUser();BeanUtils.copyProperties(userDto, sysUser);sysUser.setDelFlag(CommonConstants.STATUS_NORMAL);sysUser.setPassword(ENCODER.encode(userDto.getPassword()));baseMapper.insert(sysUser);// 循環單條保存用戶角色List<SysUserRole> userRoleList = ...; // 同上for (SysUserRole userRole : userRoleList) {sysUserRoleService.save(userRole); // ? 改為循環單條保存}return true;
}
2. 事務為何依然有效?
關鍵因素說明
??Spring 事務管理機制??@Transactional?會為整個方法創建一個??數據庫連接級的事務上下文??。
??同一事務上下文??循環中的每次?sysUserRoleService.save()?操作與用戶插入操作共享同一個事務。
??異常傳播??循環中任意一次保存失敗拋出異常時,異常會傳播到?@Transactional?注解層,觸發全局回滾。

3. 執行流程(含錯誤場景):
  1. ??正確流程??:
    用戶插入 → 角色1保存 → 角色2保存 → ... → 全部成功 → ??事務提交??

  2. ??錯誤流程??(假設第3次保存失敗):
    用戶插入 → 角色1保存 → 角色2保存 → ? 角色3保存失敗 → 拋出異常 → ??事務回滾??
    → ??已插入的用戶和角色1、2記錄均被撤銷??


重要注意事項:

1. ??性能陷阱??

?? 將?saveBatch()?批量操作改為循環單條保存會??嚴重降低性能??:

  • ??N+1 問題??:每條數據單獨執行一次 SQL(產生 N 次網絡IO + SQL 解析開銷)
  • ??對比??:saveBatch()?默認會合并為單條 SQL 或小批量提交(如?INSERT INTO table VALUES (...), (...), ...
2. ??異常處理建議??

避免在循環內捕獲異常后繼續執行(除非明確需要部分提交):

// ? 錯誤做法(導致事務失效):
for (SysUserRole userRole : userRoleList) {
try {
sysUserRoleService.save(userRole);
} catch (Exception e) {
// 捕獲后不拋出,事務無法感知異常,繼續提交后續數據!
}
}

3. ??嵌套事務風險??

如果?sysUserRoleService.save()?也有?@Transactional

  • 默認傳播行為 (REQUIRED) 會加入當前事務 → ??安全,行為一致??
  • 若改為?REQUIRES_NEW?則每次循環新建獨立事務 → ??破壞原子性(部分提交)??

結論:

  1. ??事務有效??:循環單條保存不會破壞事務的原子性,失敗時仍會全局回滾。
  2. ??避免濫用循環??:務必優先使用批量操作(如?saveBatch())以保證性能。
  3. ??統一事務上下文??:只要不修改默認的傳播行為,嵌套調用的操作仍在同一事務中。

?

?

?

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/90609.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/90609.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/90609.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

飛算 JavaAI 深度體驗:開啟 Java 開發智能化新紀元

個人主頁&#xff1a;?喜歡做夢 歡迎 &#x1f44d;點贊 ?關注 ??收藏 &#x1f4ac;評論 目錄 一、引言 二、飛算 JavaAI 初印象與功能概覽 &#xff08;一&#xff09;初識飛算 JavaAI &#xff08;二&#xff09;核心功能模塊概覽 三、智能代碼生成功能深度體…

pandas銷售數據分析

pandas銷售數據分析 數據保存在data目錄 消費者數據&#xff1a;customers.csv商品數據&#xff1a;products.csv交易數據&#xff1a;transactions.csv customers.csv數據結構&#xff1a;字段描述customer_id客戶IDgender性別age年齡region地區membership_date會員日期produc…

訪問Windows服務器備份SQL SERVER數據庫

以前沒有直接訪問過Windows服務器,今天剛一看到的是時候有點懵,竟然下意識的使用SecureCRT遠程工具去連了一下,然后領導說,看一下用戶名,突然意識到,跟我們平時遠程桌面是一樣的。 一、 win + R 打開命令窗口 二、 輸入 mstsc 三、 輸入遠程地址 四、點擊連接,如果有彈…

C++ 面向對象 - 對象定義方法匯總

C對象定義方法匯總 1. 棧上定義方式 1.1 調用無參構造函數的定義方式 無參構造函數有兩種&#xff1a; 默認無參構造函數Demo(){}默認值列表構造函數。Demo():a{1},b{2}{} // 使用初始化列表實現對象定義方式&#xff1a; Demo d; Demo d1{}; // 以下定義方式還調用了拷貝構造…

指尖上的魔法:優雅高效的Linux命令手冊

一、Linux基礎指令 1. ls ls&#xff1a;對于目錄&#xff0c;列出該目錄下的所有子目錄與文件&#xff0c;對于文件&#xff0c;將列出文件名以及其他信息。 -a&#xff1a;列出目錄下的所有文件&#xff0c;包含以.開頭的隱藏文件 -l:列出文件的詳細信息 -d&#xff1a;將目錄…

《磁力下載工具實測:資源搜索+高速下載一站式解決方案》

嘿&#xff0c;朋友們&#xff01;我是阿燦&#xff0c;今天給大家帶來一個超實用的看片神器&#xff0c;特別適合老司機們使用&#xff0c;保證讓你眼前一亮&#xff01;推薦一款比某雷更好用的下載工具&#xff0c;搭配資源搜索神器&#xff0c;輕松獲取資源不限速。超強磁力…

Go網絡編程基礎:網絡模型與協議棧概述 - 從理論到實踐的完整指南

1. 引言 在當今的互聯網時代&#xff0c;網絡編程已經成為后端開發的核心技能。Go語言以其出色的并發性能和簡潔的語法&#xff0c;在網絡編程領域展現出了強大的優勢。從Docker、Kubernetes到眾多微服務框架&#xff0c;Go已經成為構建高性能網絡應用的首選語言之一。 你是否…

Web攻防-SSTI服務端模版注入利用分類語言引擎數據渲染項目工具挖掘思路

知識點&#xff1a; 1、WEB攻防-SSTI-利用分類&功能點 2、WEB攻防-SSTI-利用項目&挖掘思路 SSTI(Server Side Template Injection) 服務器模板注入, 服務端接收了用戶的輸入&#xff0c;將其作為 Web 應用模板內容的一部分&#xff0c;在進行目標編譯渲染的過程中&…

李沐動手學深度學習Pytorch-v2筆記【07自動求導代碼實現】

文章目錄前言自動求導實現非標量變量的反向傳播分離計算Python控制流的梯度計算前言 關于走動求導的理論知識個人有點難以理解&#xff0c;推薦大家去看https://blog.csdn.net/weixin_42831564/article/details/135658138這篇文章&#xff0c;講的很好。 自動求導實現 impor…

strchr 與 strstr 函數詳解

一.strchr - 字符查找函數1.函數原型char *strchr(const char *str, int c);2.核心功能在字符串中查找特定字符的第一次出現位置3.參數說明參數 類型 說明str const char* 要搜索的字符串c int 要查找的字符&#xff08;自動轉換為char&#xff09;4.返回值…

jakes信道模型

Jakes 模型 前面我們介紹了多徑信道合成信號可表示為&#xff1a; r(t)Re{∑i0N(t)?1ai(t)u(t?τi(t))ej2πfc(t?τi(t))?Di(t)} r(t)Re \left\{\sum_{i0}^{N(t)-1}a_{i}(t)u(t-\tau_{i}(t))e^{j2\pi f_{c}(t-\tau_{i}(t))\phi_{D_{i}}(t)} \right\} r(t)…

JVM類加載機制解析

什么是類加載器&#xff1f; 類加載器是JVM的核心組件之一&#xff0c;負責將Java字節碼文件&#xff08;.class文件&#xff09;加載到JVM內存中。由于JVM只能執行二進制字節碼&#xff0c;類加載器的作用就是將編譯后的.class文件轉換為JVM可以理解和執行的格式&#xff0c;使…

用Python和OpenCV從零搭建一個完整的雙目視覺系統(二)

本系列文章旨在系統性地闡述如何利用 Python 與 OpenCV 庫&#xff0c;從零開始構建一個完整的雙目立體視覺系統。 本項目github地址&#xff1a;https://github.com/present-cjn/stereo-vision-python.git 項目架構設計&#xff1a;藍圖、分工與工作流 在上一篇文章中&#…

億級流量下的緩存架構設計:Redis+Caffeine多級緩存實戰

億級流量下的緩存架構設計&#xff1a;RedisCaffeine多級緩存實戰 一、為什么需要多級緩存&#xff1f; 在億級流量場景下&#xff0c;單純依賴Redis會遇到三大瓶頸&#xff1a;網絡延遲&#xff1a;Redis遠程訪問通常需要1-5ms&#xff0c;QPS超過10萬時成為瓶頸資源成本&…

AI基建還能投多久?高盛:2-3年不是問題,回報窗口才剛開啟

高盛表示&#xff0c;盡管AI商業化變現仍處早期階段&#xff0c;但基于成本削減的第一階段回報已經顯現。預測到2030年AI自動化可為財富500強企業節省約9350億美元成本。分析師認為&#xff0c;這一早期收益足以支撐當前AI基礎設施投資水平&#xff0c;盡管增長率可能放緩。雖然…

【mac】快捷鍵使用指南

在Mac上&#xff0c;根據選擇對象的不同&#xff0c;在選擇時移動的方法也有所不同&#xff0c;以下是具體介紹&#xff1a; 移動文件或文件夾&#xff1a;可通過拖放操作移動。打開“訪達”&#xff08;Finder&#xff09;&#xff0c;找到要移動的文件或文件夾&#xff0c;按…

CS144 lab2 tcp_receiver

1. 實驗目的 lab2 的目的是實現tcp的接收端。 主要包括兩方面 &#xff08;1&#xff09; 從發送端接收消息&#xff0c;使用Reassembler聚合字節流&#xff08;Bytestream&#xff09; &#xff08;2&#xff09;將確認號&#xff08;ackno&#xff09;和window size發回對端 …

【論文筆記】A Deep Reinforcement Learning Based Real-Time Solution Policy for the TSP

《基于 DRL 和 DCNN 的實時 TSP 求解策略》IEEE TRANSACTIONS ON INTELLIGENT TRANSPORTATION SYSTEMS, VOL. 24, NO. 6, JUNE 2023一段話總結本文提出了一種基于深度強化學習&#xff08;DRL&#xff09; 和深度卷積神經網絡&#xff08;DCNN&#xff09; 的實時旅行商問題&am…

MMaDA:多模態大型擴散語言模型

集眾家之所長&#xff0c;成大一統。普林斯頓大學、北京大學、清華大學、字節跳動的研究者將“文本推理、多模態分析、圖像生成”三大方向融合在一個單一擴散模型里&#xff0c;并用恰當的優化策略來提升模型在各個方向的性能。 研究動機 研究人員致力于開發一個能夠處理多種模…

容器技術入門與Docker環境部署

容器技術入門與Docker環境部署Docker概述什么是 DockerDocker 的優勢Docker 的應用場景Docker 核心概念(1)鏡像(2)容器(3)倉庫Docker 安裝1.關閉系統防火墻和內核2.下載Docker的repo文件3.替換倉庫地址4.更新索引文件并安裝Docker5.添加國內鏡像站6.開啟Docker服務7.優化內核參…