Spring之事務使用指南

Spring之事務使用指南

    • 一、事務的基礎概念
      • 1.1 什么是事務?
      • 1.2 事務的ACID特性
      • 1.3 Spring事務的核心優勢
    • 二、Spring事務的核心配置
    • 三、事務傳播行為(Propagation)
      • 3.1 常用傳播行為詳解
        • 3.1.1 `REQUIRED`(默認值)
        • 3.1.2 `SUPPORTS`
        • 3.1.3 `REQUIRES_NEW`
        • 3.1.4 `NEVER`
        • 3.1.5 `MANDATORY`
      • 3.2 傳播行為選擇原則
    • 四、事務隔離級別(Isolation)
      • 4.1 并發事務的三大問題
      • 4.2 隔離級別詳解
      • 4.3 配置隔離級別
    • 五、聲明式事務實戰
      • 5.1 環境準備
      • 5.2 業務實現
        • 5.2.1 Mapper接口(MyBatis)
        • 5.2.2 Service實現
      • 5.3 測試與驗證
        • 5.3.1 正常流程(無異常)
        • 5.3.2 異常流程(觸發回滾)
    • 六、常見問題與避坑指南
      • 6.1 事務不回滾(@Transactional失效)
        • 6.1.1 異常類型不匹配
        • 6.1.2 方法非public
        • 6.1.3 自調用導致事務失效
      • 6.2 事務超時(Timeout)
      • 6.3 只讀事務(readOnly)

事務是保證數據一致性的核心機制,尤其在多步操作的業務場景(如訂單創建同時扣減庫存)中不可或缺,Spring通過AOP實現了聲明式事務管理,簡化了傳統JDBC手動控制事務的繁瑣流程。

一、事務的基礎概念

1.1 什么是事務?

事務(Transaction)是由一系列數據庫操作組成的邏輯單元,這些操作要么全部成功,要么全部失敗(如“創建訂單”需同時執行“插入訂單記錄”和“扣減庫存”,兩者必須同時成功或同時失敗)。

1.2 事務的ACID特性

事務必須滿足ACID特性,這是保證數據一致性的基礎:

  • 原子性(Atomicity):事務中的操作要么全執行,要么全不執行(如轉賬時“扣款”和“入賬”必須同時成功);
  • 一致性(Consistency):事務執行前后,數據從一個有效狀態變為另一個有效狀態(如轉賬前后總金額不變);
  • 隔離性(Isolation):多個事務并發執行時,彼此不干擾(避免臟讀、不可重復讀等問題);
  • 持久性(Durability):事務提交后,修改永久保存到數據庫(即使斷電也不丟失)。

1.3 Spring事務的核心優勢

傳統JDBC事務需要手動控制(conn.setAutoCommit(false)commit()rollback()),而Spring事務的優勢在于:

  • 聲明式事務:通過注解(@Transactional)或XML配置事務,無需編寫事務控制代碼;
  • AOP實現:事務邏輯與業務邏輯分離,業務代碼只關注核心邏輯;
  • 靈活配置:支持自定義傳播行為、隔離級別、超時時間等;
  • 整合方便:與Spring容器無縫集成,支持各種數據源和ORM框架(如MyBatis、Hibernate)。

二、Spring事務的核心配置

Spring事務的核心是@Transactional注解,通過屬性配置事務行為,常用屬性如下:

屬性名作用默認值
propagation事務傳播行為(如何處理嵌套事務)Propagation.REQUIRED
isolation事務隔離級別(并發控制)Isolation.DEFAULT(數據庫默認)
readOnly是否為只讀事務(優化性能)false
timeout事務超時時間(秒,超時自動回滾)-1(無超時)
rollbackFor需要回滾的異常類型(如Exception.classRuntimeException及其子類
noRollbackFor不需要回滾的異常類型

三、事務傳播行為(Propagation)

事務傳播行為定義了“當一個事務方法調用另一個事務方法時,事務如何傳播”,是Spring事務最核心的特性之一。

3.1 常用傳播行為詳解

3.1.1 REQUIRED(默認值)
  • 規則:如果當前存在事務,則加入該事務;如果沒有事務,則創建新事務。
  • 適用場景:大多數業務方法(如訂單創建、用戶注冊)。
@Service
public class OrderService {@Autowiredprivate OrderMapper orderMapper;@Autowiredprivate StockService stockService;// 傳播行為:REQUIRED(默認)@Transactional(propagation = Propagation.REQUIRED)public void createOrder(Order order) {orderMapper.insert(order); // 操作1stockService.reduceStock(order.getProductId()); // 調用另一個事務方法}
}@Service
public class StockService {// 傳播行為:REQUIRED@Transactional(propagation = Propagation.REQUIRED)public void reduceStock(Long productId) {// 操作2:扣減庫存}
}

執行邏輯
createOrder創建事務→reduceStock加入該事務→若操作1或2失敗,整個事務回滾(符合原子性)。

3.1.2 SUPPORTS
  • 規則:如果當前存在事務,則加入該事務;如果沒有事務,則以非事務方式執行。
  • 適用場景:可選事務的方法(如查詢操作,可在事務中執行,也可單獨執行)。
@Service
public class UserService {// 傳播行為:SUPPORTS@Transactional(propagation = Propagation.SUPPORTS)public User getUserById(Long id) {// 查詢用戶(非核心操作,有無事務均可)}
}
3.1.3 REQUIRES_NEW
  • 規則:無論當前是否存在事務,都創建新事務(原事務暫停,新事務獨立執行)。
  • 適用場景:需要獨立事務的操作(如日志記錄,即使主事務失敗也需提交)。
@Service
public class OrderService {@Autowiredprivate LogService logService;@Transactionalpublic void createOrder(Order order) {// 主事務操作:創建訂單logService.recordLog("創建訂單:" + order.getId()); // 調用獨立事務方法}
}@Service
public class LogService {// 傳播行為:REQUIRES_NEW(獨立事務)@Transactional(propagation = Propagation.REQUIRES_NEW)public void recordLog(String content) {// 記錄日志(即使主事務回滾,此操作仍會提交)}
}

執行邏輯
主事務執行→recordLog創建新事務→日志記錄成功提交→主事務若失敗,僅主事務回滾,日志不會回滾

3.1.4 NEVER
  • 規則:如果當前存在事務,則拋出異常;如果沒有事務,則以非事務方式執行。
  • 適用場景:絕對不能在事務中執行的方法(如某些特殊查詢)。
3.1.5 MANDATORY
  • 規則:如果當前存在事務,則加入該事務;如果沒有事務,則拋出異常。
  • 適用場景:必須在事務中執行的方法(如核心業務操作)。

3.2 傳播行為選擇原則

  • 核心業務方法(如訂單、支付):REQUIRED
  • 查詢方法:SUPPORTS
  • 獨立日志、審計操作:REQUIRES_NEW
  • 必須在事務中執行的方法:MANDATORY

四、事務隔離級別(Isolation)

事務隔離級別定義了“多個事務并發執行時的隔離程度”,用于解決并發問題(臟讀、不可重復讀、幻讀)。

4.1 并發事務的三大問題

問題說明示例
臟讀讀取到另一個未提交事務的修改事務A修改數據→事務B讀取→事務A回滾→事務B讀取到無效數據
不可重復讀同一事務中多次讀取數據不一致事務A讀取數據→事務B修改并提交→事務A再次讀取,數據不同
幻讀同一事務中多次查詢,結果集數量不一致事務A查詢所有訂單→事務B新增訂單并提交→事務A再次查詢,多了一條記錄

4.2 隔離級別詳解

Spring支持5種隔離級別,對應數據庫的隔離級別:

隔離級別解決問題并發性能適用場景
DEFAULT(默認)數據庫默認隔離級別(如MySQL默認REPEATABLE_READ中等大多數場景(推薦)
READ_UNCOMMITTED無(允許臟讀、不可重復讀、幻讀)最高極少使用(對一致性要求極低)
READ_COMMITTED解決臟讀較高對一致性有基本要求(如Oracle默認)
REPEATABLE_READ解決臟讀、不可重復讀中等MySQL默認,大多數業務場景
SERIALIZABLE解決所有問題(串行執行)最低對一致性要求極高(如金融交易)

4.3 配置隔離級別

@Service
public class OrderService {// 設置隔離級別為REPEATABLE_READ@Transactional(isolation = Isolation.REPEATABLE_READ)public void createOrder(Order order) {// 業務邏輯}
}

注意:隔離級別受數據庫支持限制(如MySQL支持所有級別,SQL Server不支持READ_UNCOMMITTED),實際以數據庫為準。

五、聲明式事務實戰

以“訂單創建”為例,演示事務的完整使用(包含傳播行為、異常回滾配置)。

5.1 環境準備

添加Spring事務依賴(已包含在spring-context中),并配置數據源和事務管理器:

@Configuration
@MapperScan("com.example.mapper")
public class SpringConfig {// 數據源配置(省略,需配置正確的JDBC連接)@Beanpublic DataSource dataSource() { ... }// 事務管理器(核心)@Beanpublic PlatformTransactionManager transactionManager(DataSource dataSource) {return new DataSourceTransactionManager(dataSource);}
}

5.2 業務實現

5.2.1 Mapper接口(MyBatis)
public interface OrderMapper {void insert(Order order);
}public interface StockMapper {void reduceStock(@Param("productId") Long productId, @Param("quantity") Integer quantity);
}
5.2.2 Service實現
@Service
public class OrderService {@Autowiredprivate OrderMapper orderMapper;@Autowiredprivate StockService stockService;/*** 創建訂單(核心業務)* 傳播行為:REQUIRED(默認)* 回滾規則:所有Exception都回滾(默認僅RuntimeException回滾,此處擴展)*/@Transactional(rollbackFor = Exception.class)public void createOrder(Order order) throws Exception {// 1. 創建訂單orderMapper.insert(order);// 2. 扣減庫存(調用另一個事務方法)stockService.reduceStock(order.getProductId(), order.getQuantity());// 3. 模擬異常(測試回滾)if (order.getTotalAmount() < 0) {throw new Exception("訂單金額不能為負"); // 觸發回滾}}
}@Service
public class StockService {@Autowiredprivate StockMapper stockMapper;// 傳播行為:REQUIRED(加入訂單事務)@Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)public void reduceStock(Long productId, Integer quantity) {stockMapper.reduceStock(productId, quantity);// 若庫存不足,拋出異常(觸發回滾)if (/* 庫存不足 */) {throw new RuntimeException("庫存不足");}}
}

5.3 測試與驗證

5.3.1 正常流程(無異常)
@Test
public void testCreateOrderSuccess() {Order order = new Order();order.setProductId(1L);order.setQuantity(2);order.setTotalAmount(100.0);orderService.createOrder(order);// 驗證:訂單表新增記錄,庫存表數量減少(事務提交成功)
}
5.3.2 異常流程(觸發回滾)
@Test
public void testCreateOrderRollback() {Order order = new Order();order.setProductId(1L);order.setQuantity(2);order.setTotalAmount(-100.0); // 觸發異常try {orderService.createOrder(order);} catch (Exception e) {// 驗證:訂單表無新增記錄,庫存表數量未變(事務回滾成功)}
}

六、常見問題與避坑指南

6.1 事務不回滾(@Transactional失效)

6.1.1 異常類型不匹配

問題:方法拋出CheckedException(如Exception),但rollbackFor未配置,導致事務不回滾。

原因@Transactional默認只對RuntimeException及其子類回滾,對CheckedException不回滾。

解決方案
通過rollbackFor指定需要回滾的異常:

// 對所有Exception回滾
@Transactional(rollbackFor = Exception.class)
6.1.2 方法非public

問題:非public方法(如privateprotected)的@Transactional無效。

原因:Spring AOP默認只對public方法增強(事務基于AOP實現)。

解決方案
確保事務方法為public

6.1.3 自調用導致事務失效

問題:同一類中方法調用(自調用)時,事務不生效。

@Service
public class OrderService {public void methodA() {methodB(); // 自調用,事務不生效}@Transactionalpublic void methodB() { ... }
}

原因:Spring事務基于代理對象,自調用是目標對象內部調用,未經過代理。

解決方案

  1. 注入自身代理對象調用:
@Service
public class OrderService {@Autowiredprivate OrderService orderService; // 注入自身代理public void methodA() {orderService.methodB(); // 通過代理調用,事務生效}@Transactionalpublic void methodB() { ... }
}
  1. 開啟暴露代理(@EnableAspectJAutoProxy(exposeProxy = true)),通過AopContext獲取代理:
public void methodA() {((OrderService) AopContext.currentProxy()).methodB();
}

6.2 事務超時(Timeout)

問題:事務執行時間過長,占用數據庫連接,導致連接池耗盡。

解決方案
設置合理的超時時間(秒),超時自動回滾并釋放連接:

// 超時時間30秒
@Transactional(timeout = 30)
public void createOrder(Order order) { ... }

6.3 只讀事務(readOnly)

對查詢方法設置readOnly = true,提示數據庫優化事務(如避免寫操作、啟用緩存):

// 只讀事務(查詢方法)
@Transactional(readOnly = true)
public List<Order> getOrders() { ... }

注意:只讀事務中執行insert/update會拋出異常(取決于數據庫)。

總結:事務使用的最佳實踐
Spring事務簡化了事務管理,但需遵循最佳實踐避免常見問題:

  1. 核心配置
  • 對所有業務方法顯式指定rollbackFor = Exception.class(避免異常不回滾);
  • 核心業務用REQUIRED傳播行為,獨立操作(如日志)用REQUIRES_NEW
  • 查詢方法設置readOnly = true優化性能。
  1. 避坑要點
  • 事務方法必須為public
  • 避免自調用(或通過代理對象調用);
  • 合理設置超時時間,避免長事務。
  1. 性能優化
  • 事務范圍盡可能小(僅包含必要操作,避免在事務中調用外部接口、等待用戶輸入);
  • 讀多寫少場景用較高隔離級別(如READ_COMMITTED),減少鎖競爭。

事務是保證數據一致性的最后一道防線,正確使用能避免數據錯亂(如重復下單、庫存超賣)等嚴重問題。建議在開發中結合日志(如打印事務開始/提交/回滾日志)和測試(模擬異常驗證回滾)確保事務生效。

若這篇內容幫到你,動動手指支持下!關注不迷路,干貨持續輸出!
ヾ(′? ˋ)ノヾ(′? ˋ)ノヾ(′? ˋ)ノヾ(′? ˋ)ノヾ(′? ˋ)ノ

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

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

相關文章

基于FPGA的多級流水線加法器verilog實現,包含testbench測試文件

目錄 1.課題概述 2.系統仿真結果 3.核心程序 4.系統原理簡介 5.參考文獻 6.完整工程文件 1.課題概述 流水線&#xff08;Pipeline&#xff09;技術源于工業生產中的裝配線理念&#xff0c;在數字電路中&#xff0c;它將一個復雜運算任務分解為若干個子任務&#xff0c;每…

5.1.4習題精講

一、單項選擇題 01. 下列部件不屬于控制器的是&#xff08; C &#xff09;。 題目原文 下列部件不屬于控制器的是&#xff08; &#xff09;。 A. 指令寄存器 B. 程序計數器 C. 程序狀態字寄存器 D. 時序電路 正確答案&#xff1a;C 題目解析 考點分析&#xff1a; 本題考察CP…

華為云Flexus+DeepSeek征文|低代碼 × 強推理:華為云 Flexus 搭建可部署的 AI Agent 實踐方案【搭建寵物養護小知識AI助手】

文章目錄華為云FlexusDeepSeek征文&#xff5c;低代碼 強推理&#xff1a;華為云 Flexus 搭建可部署的 AI Agent 實踐方案【搭建寵物養護小知識AI助手】&#x1f680; 引言一、核心技術概覽1. 華為云 Flexus X2. DeepSeek-R1 模型3. Dify 平臺二、總體架構設計三、環境準備與資…

基于智慧經營系統的學校住宿登記報表分析與應用探究-畢業論文—仙盟創夢IDE

摘要本文聚焦學校住宿場景&#xff0c;以 “未來之窗智慧經營&#xff08;學校住宿&#xff09;” 系統生成的日報表、昨日報表、本月報表為研究對象&#xff0c;深入剖析報表數據結構、功能價值及在住宿管理中的應用。通過解讀水費、電費、押金、房費、總計、訂單等數據維度&a…

arping(ARP協議網絡測試工具)

1. 項目介紹&#xff1a;arping 是一個用于在局域網&#xff08;LAN&#xff09;中查找特定 IP 地址是否被占用的實用工具。與傳統的 ping 命令不同&#xff0c;arping 使用 ARP 協議來發送和接收數據包&#xff0c;從而能夠檢測到那些阻止 ICMP 請求的主機。arping 可以幫助網…

【UE5醫學影像可視化】讀取dicom數據生成2D紋理并顯示

文章目錄1.實現目標2.實現過程2.1 數據準備2.2 創建項目2.3 dcmtk庫集成2.4 流程&原理2.5 材質2.6 應用實現3.參考資料1.實現目標 本文在UE5中讀取本地的dicom文件&#xff0c;解析像素值、窗寬窗位等信息&#xff0c;生成2D紋理&#xff0c;在UE場景中實現簡單的2D醫學影像…

lua(xlua)基礎知識點記錄一

1. 關于 (…) 操作符 編譯階段優化&#xff1a;Lua 編譯器會對常量字符串進行優化處理&#xff0c;將連續的字符串拼接操作 (…) 合并為單個字符串。這種優化僅適用于編譯期確定的常量字符串&#xff0c;不適用于運行時生成的動態字符串。 示例&#xff1a;local str "He…

【Python數據采集】Python爬取小紅書搜索關鍵詞下面的所有筆記的內容、點贊數量、評論數量等數據,繪制詞云圖、詞頻分析、數據分析

Python爬取小紅書搜索關鍵詞下面的所有筆記的內容、點贊數量、評論數量等數據&#xff0c;繪制詞云圖、詞頻分析、數據分析 使用 Python 編寫一個簡單的爬蟲程序來從小紅書抓取與指定關鍵詞相關的筆記數據&#xff0c;并對這些數據進行基本的數據分析&#xff0c;包括詞云圖和…

最大子數組和問題-詳解Kadane算法

最大子數組和問題-詳解Kadane算法一、問題定義與暴力解法1.1 問題描述1.2 暴力解法的低效性二、Kadane算法的核心原理2.1 動態規劃思想的應用2.2 優化空間復雜度三、Kadane算法的Java實現3.1 基礎版本&#xff08;處理所有情況&#xff09;3.2 算法正確性驗證四、Kadane算法的變…

Mongoose網絡庫深度解析:從單線程到多線程的架構演進

0. 引言&#xff1a;C/C網絡編程的困境與突破 在C/C開發領域&#xff0c;網絡編程一直是一個令人頭疼的問題。與Python的requests庫或Go的net/http包不同&#xff0c;C/C缺乏統一的包管理體系和標準化的網絡API。開發者往往需要面對gcc/msvc版本差異、平臺兼容性問題、以及各種…

Jfinal+SQLite處理 sqlite數據庫執行FIND_IN_SET報錯

方法一原代碼sql " and FIND_IN_SET(s.M_ID," ids ")"; 修改為 sql " where s.M_ID"getInSql(ids);public static String getInSql(String ids) {String[] idArray ids.split(",");StringBuilder sql new StringBuilder(" I…

day24——Java高級技術深度解析:單元測試、反射、注解與動態代理

文章目錄一、單元測試&#xff1a;JUnit框架精要1.1 單元測試核心概念1.2 JUnit快速入門實戰基礎步驟&#xff1a;斷言機制驗證結果1.3 JUnit核心注解解析二、反射機制&#xff1a;框架設計的基石2.1 反射核心概念2.2 獲取Class對象的三種方式2.3 反射操作類成分獲取并執行構造…

網頁的性能優化,以及具體的應用場景

下面是每個性能優化技術的具體應用場景示例&#xff0c;結合代碼說明如何在實際項目中使用這些優化方法&#xff1a; 1. 批量DOM操作與DocumentFragment 應用場景&#xff1a;動態渲染大量列表項&#xff08;如評論區、商品列表&#xff09; 問題&#xff1a;逐個添加DOM元素會…

Fiddler 中文版 API 調試與性能優化實踐 官方中文網全程支持

在現代開發中&#xff0c;性能問題往往是產品上線后最容易被忽視的一環&#xff0c;尤其是API接口性能。一旦接口響應時間過長或在高并發場景下出現性能瓶頸&#xff0c;可能直接影響用戶體驗和系統穩定性。對于開發者來說&#xff0c;如何精確地找到瓶頸所在&#xff0c;如何模…

嵌入式硬件篇---機械臂運動學解算(3自由度)

實際 3 自由度機械臂的解算是機器人控制的核心&#xff0c;涉及運動學正解&#xff08;關節角度→末端位姿&#xff09;和逆解&#xff08;目標位姿→關節角度&#xff09;。以下從結構建模、解算方法、代碼實現和應用場景四個維度詳細展開&#xff0c;結合工業級機械臂的典型場…

在攝像機視圖中想像在普通 3D 視口里那樣隨意移動

有兩條最常用的方法&#xff1a;1. 「鎖定相機到視圖」(Lock Camera to View)步驟進入相機視圖&#xff1a;按 Numpad 0&#xff08;若無數字鍵盤&#xff0c;可在 Edit → Preferences → Input 勾選 Emulate Numpad 后用主鍵盤 0&#xff09;。右側呼出 N 面板&#xff0c;切…

An End-to-End Attention-Based Approach for Learning on Graphs NC 2025

NC 2025 | 一種基于端到端注意力機制的圖學習方法 Nature Communications IF=15.7 綜合性期刊 1區 參考:https://mp.weixin.qq.com/s/cZ-d8Sf8wtQ9wfcGOFimCg 今天介紹一篇發表在 Nature Communications 的圖學習論文《An end-to-end attention-based approach for learnin…

【牛客刷題】小紅的數字串

文章目錄 一、題目描述 1.1 輸入描述 1.2 輸出描述 1.3 示例1 二、高效解法 2.1 核心算法設計 2.2 算法設計理念 2.2.1 算法流程詳解 2.2.2 復雜度分析 2.3 算法優勢分析 2.3.1 關鍵優化點 2.3.2 正確性驗證 2.4 邊界處理 2.5 總結與擴展 一、題目描述 小紅拿到了一個數字串(由…

微算法科技技術創新,將量子圖像LSQb算法與量子加密技術相結合,構建更加安全的量子信息隱藏和傳輸系統

隨著信息技術的發展&#xff0c;數據的安全性變得尤為重要。在傳統計算模式下&#xff0c;即便采用復雜的加密算法&#xff0c;也難以完全抵御日益增長的網絡攻擊威脅。量子計算技術的出現為信息安全帶來了新的解決方案。然而&#xff0c;量子圖像處理領域仍面臨復雜度高、效率…

博客摘錄「 Springboot入門到精通(超詳細文檔)」2025年7月4日

1.Spring Boot返回Json數據及數據封裝1. Controller 中使用RestController注解即可返回 Json 格式的數據首先看看RestController注解包含了什么東西&#xff0c; ResponseBody 注解是將返回的數據結構轉換為 Json 格式Target({ElementType.TYPE}) Retention(RetentionPolicy.RU…