Spring Boot 事務失效的八大原因及解決方案詳解

在 Spring Boot 項目開發中,聲明式事務管理通過 @Transactional 注解提供了極大的便利。

但許多開發者都曾遇到過事務不生效的困擾。

本文將詳細分析導致 Spring Boot 事務失效的八大常見情況,并提供相應的解決方案。

1. 數據庫引擎不支持事務

問題分析:這是最根本的原因。如果數據庫存儲引擎本身不支持事務(如 MySQL 的 MyISAM),那么無論 Spring 如何配置,事務都不會生效。

解決方案

  • 確保你的數據庫表使用支持事務的引擎,如 MySQL 的 InnoDB
  • 建表時指定存儲引擎:CREATE TABLE ... ENGINE=InnoDB;

2. 事務方法非 public 修飾

問題分析@Transactional 基于 Spring AOP 實現,而 AOP 代理默認無法攔截非 public 方法。

@Service
public class UserService {@Transactional // 失效!private void createUser(User user) {userMapper.insert(user);}
}

解決方案

  • 始終將 @Transactional 注解應用于 public 方法上

3. 自調用問題(Within-Class Invocation)

問題分析:這是最常見且最容易踩坑的原因。當一個類中的非事務方法調用同一個類中的 @Transactional 方法時,事務不會生效。

@Service
public class UserService {public void createUser(User user) {// 一些非事務操作this.insertUser(user); // 自調用,事務失效!}@Transactionalpublic void insertUser(User user) {userMapper.insert(user);// 如果這里出現異常,事務不會回滾}
}

解決方案

  • 推薦方案:將事務方法抽取到另一個 Service 類中
  • 通過 ApplicationContext 獲取代理對象調用(不優雅)
  • 使用 AspectJ 模式的事務管理(配置復雜)

4. 異常類型不正確或被捕獲

問題分析@Transactional 默認只在拋出運行時異常(RuntimeException)和 Error 時回滾。

@Transactional
public void method() throws Exception {// 數據庫操作throw new Exception("受檢異常"); // 事務不會回滾!
}

另一個陷阱:異常被捕獲但未重新拋出

@Transactional
public void method() {try {int i = 1 / 0; // 拋出 RuntimeException} catch (Exception e) {e.printStackTrace(); // 只是打印,事務不會回滾!}
}

解決方案

  • 使用 rollbackFor 屬性指定回滾的異常類型:
@Transactional(rollbackFor = Exception.class)
  • 在 catch 塊中重新拋出運行時異常

5. 傳播行為(Propagation)設置不當

問題分析:錯誤配置傳播行為會導致意外結果。

@Transactional(propagation = Propagation.NOT_SUPPORTED) // 不以事務運行
public void method() {// 這里沒有事務
}

解決方案

  • 根據業務需求正確配置傳播行為
  • 理解各種傳播行為的含義:
    • REQUIRED(默認):支持當前事務,不存在則新建
    • REQUIRES_NEW:新建事務,掛起當前事務
    • NOT_SUPPORTED:非事務方式執行
    • NEVER:非事務方式執行,存在事務則拋出異常

6. 未被 Spring 容器管理

問題分析:如果類沒有加上 @Service, @Component 等注解,它就不是 Spring Bean,其上的 @Transactional 注解不會被掃描。

// 缺少 @Service 注解
public class UserService {@Transactional // 失效!public void createUser(User user) {// ...}
}

解決方案

  • 確保類被 Spring 管理,添加適當的注解

7. 多線程環境下調用

問題分析:事務信息存儲在 ThreadLocal 中,新線程中的操作不屬于原事務。

@Transactional
public void method() {new Thread(() -> {userMapper.insert(user); // 不在事務中!}).start();
}

解決方案

  • 避免在事務方法中創建異步線程進行數據庫操作
  • 使用分布式事務解決方案處理跨線程事務

8. 配置問題

問題分析

  • 未開啟事務管理(雖然 Spring Boot 會自動配置)
  • 多數據源未正確配置事務管理器

解決方案

  • 確保配置了 @EnableTransactionManagement(Spring Boot 通常自動配置)
  • 多數據源時為每個數據源配置對應的事務管理器:
@Bean
public PlatformTransactionManager transactionManager(DataSource dataSource) {return new DataSourceTransactionManager(dataSource);
}
  • 使用 @Transactional(value = "txManagerName") 指定事務管理器

事務調試技巧

開啟事務調試日志,在 application.properties 中添加:

logging.level.org.springframework.transaction.interceptor=TRACE
logging.level.org.springframework.jdbc.datasource.DataSourceTransactionManager=DEBUG

這將幫助你看清事務何時開啟、回滾或提交。

總結

Spring Boot 事務失效通常由以上八大原因導致,其中自調用問題最為常見。要確保事務正常工作,需要:

  1. 使用支持事務的數據庫引擎(如 InnoDB)
  2. @Transactional 應用于 public 方法
  3. 避免自調用,將事務方法放在不同類中
  4. 正確處理異常,確保異常能夠觸發回滾
  5. 正確配置傳播行為
  6. 確保 Bean 被 Spring 管理
  7. 避免多線程事務問題
  8. 檢查事務相關配置

希望本文能幫助你有效解決 Spring Boot 中的事務失效問題。

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

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

相關文章

數據結構:順序棧與鏈棧的原理、實現及應用

數據結構詳解:順序棧與鏈棧的原理、實現及應用 1. 引言:棧的核心概念 棧(Stack)是一種重要的線性數據結構,它遵循后進先出(Last In First Out, LIFO)的原則。這意味著最后一個被添加到棧中的元素…

apipost 8.x 腳本循環調用接口

apipost 8.x 腳本循環調用接口背景實現先說整體邏輯:最后背景 上周為了找某OA 偶爾出現的詭異現象,需要用測試工具來壓測,看看這個問題能否重現。以前用過Jmeter,但是沒有裝,正好有個國產的apipost看看如何&#xff1…

STM32 - Embedded IDE - GCC - 使用 GCC 鏈接腳本限制 Flash 區域

導言如上所示,Keil限制flash區域只需要在IROM1里將Start框框與Size框框填入具體信息即可。比如bootloader程序一般從0x8000000開始,大小0x10000(64KB)。此時,flash的范圍被限制在0x8000000 ~ 0x800FFFF。 另外&#xf…

Jenkins和Fastlane的原理、優缺點、用法、如何選擇

Jenkins 和 Fastlane 是軟件開發中用于自動化流程的工具一、Jenkins實現自動化打包1.1具體實現步驟安裝與配置:首先在服務器上安裝 Jenkins,可以通過官方提供的安裝包進行安裝,支持多種操作系統。安裝完成后,通過 Web 界面進行初始…

DOM常見的操作有哪些?

1.DOM文檔對象模型(DOM)是HTML和XML文檔的編程接口它提供了對文檔結構化表述,并定義了一種方式可以使從程序中對該結構進行訪問,從而改變文檔的結構,樣式和內容任何HTML或XML文檔都可以用DOM表示一個由節點構成的層級結…

【Kubernetes】知識點3

25. 說明Job與CronJob的功能。答:Job:一次性作業,處理短暫的一次性任務,僅執行一次,并保證處理的一個或者多個 Pod 成功結束。CronJob:周期性作業,可以指定每過多少周期執行一次任務。26. Kuber…

LINUX-網絡編程-TCP-UDP

1.目的:不同主機,進程間通信。2.解決的問題1)主機與主機之間物理層面必須互相聯通。2)進程與進程在軟件層面必須互通。IP地址:計算機的軟件地址,用來標識計算機設備MAC地址:計算機的硬件地址&am…

目標檢測定位損失函數:Smooth L1 loss 、IOU loss及其變體

Smooth L1 Loss 概述 Smooth L1 Loss(平滑 L1 損失),是一個在回歸任務,特別是計算機視覺中的目標檢測領域(如 Faster R-CNN, SSD)非常核心的損失函數。 xxx 表示模型的預測值,yyy 表示真實值&am…

Android開發之fileprovider配置路徑path詳細說明

第一步在清單文件配置fileprovider屬性<providerandroid:name"androidx.core.content.FileProvider"android:authorities"${applicationId}.fileprovider"android:exported"false"android:grantUriPermissions"true"><meta-d…

【ComfyUI】圖像描述詞潤色總結

在 ComfyUI 的工作流中&#xff0c;圖像反推描述詞能幫我們從圖像里抽取語義信息&#xff0c;但這些原始描述往往還顯得生硬&#xff0c;缺乏創意或流暢性。為了讓提示詞更自然、更有表現力&#xff0c;就需要“潤色”環節。潤色節點的任務&#xff0c;不是重新生成描述&#x…

java面試中經常會問到的IO、NIO問題有哪些(基礎版)

文章目錄一、IO 基礎與分類二、NIO 核心組件與原理三、NIO 與 BIO 的實戰對比四、AIO 與 NIO 的區別五、Netty 相關&#xff08;NIO 的高級應用&#xff09;總結Java 中的 IO&#xff08;輸入輸出&#xff09;和 NIO&#xff08;非阻塞 IO&#xff09;是面試中的重要考點&#…

時序數據庫選型指南:如何為工業場景挑選最強“數據底座”

工業4.0時代&#xff0c;工廠化身為巨大的數據生產中心。數以萬計的傳感器、PLC和設備每時每刻都在產生著海量的時間序列數據&#xff08;Time-Series Data&#xff09;&#xff1a;溫度、壓力、流速、振動、設備狀態……這些帶時間戳的數據是工業互聯網的血液&#xff0c;蘊含…

【排序算法】冒泡 選排 插排 快排 歸并

一、冒泡排序// 冒泡排序var bubbleSort function (arr) {const len arr.length;for (let i 0; i < len; i) {let isSwap false;for (let j 0; j < len - 1; j) {// 每一次遍歷都要比較相鄰元素的大小&#xff0c;如果滿足條件就交換位置if (arr[j] > arr[j 1])…

電子病歷空缺句的語言學特征描述與自動分類探析(以GPT-5為例)(中)

語言學特征刻畫(特征庫) 句法特征 句法特征是識別 SYN 類電子病歷空缺句的核心語言學維度,其量化分析通過構建依存句法結構的形式化指標,實現對語法不完整性的客觀描述。該類特征主要包括依存樹不完備指標、謂詞-論元覆蓋率及從屬連詞未閉合三類核心參數,共同構成 SYN 類…

InnoDB存儲引擎-事務

1. 事務概述事務可由一條簡單的SQL語句組成,也可以由一組復雜的SQL語句組成. 事務是訪問并更新數據庫中各種數據項的一個程序執行單元. 在事務中的操作, 要么都做修改, 要么都不做. 對于 InnoDB存儲引擎而言, 其默認的事務隔離級別 RR , 完全遵循和滿足了事務的 ACID 特性. 1.1…

web項目的目錄結構

web項目的目錄結構 WEB-INF 存放class文件、jar文件和配置文件&#xff0c;對于用戶來說該文件夾是不可見的WEB-INF/web.xml web應用程序的描述文件&#xff0c;用來配置資源&#xff0c;如servlet、過濾器、監聽器等WEB-INF/classes 用于存放class文件&#xff0c;也是該web應…

數據結構_隊列Queue(C語言實現)

一、隊列的基本概念 1.隊列定義 隊列是一種先進先出的線性表數據結構&#xff08;First in First out&#xff09;,現實中的例子就是&#xff0c;排隊購票&#xff0c;先排隊的先購票&#xff0c;購完票之后直接從這個隊中離開&#xff0c;后來的在這個隊后面排隊&#xff0c;這…

C++對CPU緩存的合理利用

緩存體系 在計算機的體系結構中,存儲速度是分了好幾層: CPU緩存,又分成了L1/L2/L3等多層緩存,我們暫時看成同一層。訪問速度最快 內存,訪問速度次之,大概是CPU緩存的幾十分之一 硬盤,訪問速度最慢,是內存訪問速度的幾十分之一 所以,在計算機體系結構中,把下一層的數…

貝葉斯定理:理解概率更新與實際場景應用

貝葉斯定理及其應用&#xff1a;從基礎到實戰 貝葉斯定理&#xff08;Bayes’ Theorem&#xff09;是概率論中最基礎也是最強大的工具之一。它通過將先驗知識與新證據結合&#xff0c;能夠幫助我們在不確定的情況下做出更加精準的判斷。本文將從貝葉斯定理的核心概念、公式開始…

組件之間的傳遞參數傳遞(常用父向子傳遞)

現在&#xff0c;有子組件<MdsWxSourceDetailref"mdsWx":rank-obj"activeRankObj":media-name"activeObj.mediaName" :error-info"activeErrorInfo" ></MdsWxSourceDetail>以上代碼在MdsIndexRankDetail&#xff0…