Java 事務失效場景全解析

在 Java 開發中,事務管理是保證數據一致性的核心機制,尤其是在 Spring 框架中,@Transactional注解的使用極大簡化了事務配置。然而,在實際開發中,事務常常會因為一些細節問題而失效,導致數據異常。本文將詳細解析 Java 事務失效的八大場景,每個場景都提供代碼示例與對應的修復方案。

一、事務方法非 public 修飾

失效原理

Spring 的@Transactional注解默認只對public方法生效。這是因為 Spring AOP 在實現事務管理時,無論是 JDK 動態代理還是 CGLIB 代理,都無法對非 public 方法(private、protected、默認訪問權限)進行有效的事務增強。

失效代碼

java運行

@Service
public class UserService {// 非public方法,事務注解失效@Transactionalvoid updateUser(Long id) { userMapper.updateStatus(id, 1);}
}

修復方案

將事務方法修改為public訪問權限。

修復后代碼

java運行

@Service
public class UserService {// 修改為public方法,事務生效@Transactionalpublic void updateUser(Long id) { userMapper.updateStatus(id, 1);}
}

二、異常被捕獲且未重新拋出

失效原理

Spring 事務默認僅在遇到未捕獲的RuntimeExceptionError時觸發回滾。如果方法內部使用try-catch捕獲了異常且未重新拋出,事務管理器會認為沒有異常發生,從而不會執行回滾操作。

失效代碼

java運行

@Service
public class OrderService {@Transactionalpublic void createOrder(Order order) {try {orderMapper.insert(order);// 模擬異常int i = 1 / 0;} catch (Exception e) {// 捕獲異常但未拋出,事務不會回滾log.error("創建訂單失敗", e);}}
}

修復方案

方案一:捕獲異常后重新拋出
方案二:使用TransactionAspectSupport手動觸發回滾

修復后代碼(方案一)

java運行

@Service
public class OrderService {@Transactionalpublic void createOrder(Order order) {try {orderMapper.insert(order);// 模擬異常int i = 1 / 0;} catch (Exception e) {log.error("創建訂單失敗", e);// 重新拋出異常,觸發事務回滾throw new RuntimeException("創建訂單失敗", e);}}
}

修復后代碼(方案二)

java運行

@Service
public class OrderService {@Transactionalpublic void createOrder(Order order) {try {orderMapper.insert(order);// 模擬異常int i = 1 / 0;} catch (Exception e) {log.error("創建訂單失敗", e);// 手動觸發事務回滾TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();}}
}

三、錯誤配置 rollbackFor 屬性

失效原理

@TransactionalrollbackFor屬性用于指定需要回滾的異常類型,默認值為{RuntimeException.class, Error.class}。如果業務中拋出的是受檢查異常(如IOExceptionSQLException),且未在rollbackFor中聲明,事務不會回滾。

失效代碼

java運行

@Service
public class FileService {// 未指定rollbackFor,受檢查異常不會觸發回滾@Transactionalpublic void importData(String filePath) throws IOException {// 讀取文件(可能拋出IOException)FileReader reader = new FileReader(filePath);// 數據入庫操作dataMapper.batchInsert(parseData(reader));}
}

修復方案

顯式指定rollbackFor屬性,包含需要回滾的異常類型。

修復后代碼

java運行

@Service
public class FileService {// 顯式指定rollbackFor包含IOException@Transactional(rollbackFor = {IOException.class, RuntimeException.class})public void importData(String filePath) throws IOException {FileReader reader = new FileReader(filePath);dataMapper.batchInsert(parseData(reader));}
}// 更通用的方式:捕獲所有Exception
@Service
public class FileService {@Transactional(rollbackFor = Exception.class)public void importData(String filePath) throws IOException {// 業務邏輯不變}
}

四、事務傳播機制配置不當

失效原理

Spring 事務的傳播機制決定了事務方法之間的嵌套行為。若傳播機制配置不合理(如使用NOT_SUPPORTEDSUPPORTS等),可能導致操作不在事務中執行。

失效代碼

java運行

@Service
public class OrderService {@Autowiredprivate PaymentService paymentService;@Transactionalpublic void createOrder(Order order) {orderMapper.insert(order);// 調用支付服務(非事務方式執行)paymentService.processPayment(order.getId(), order.getAmount());}
}@Service
public class PaymentService {// 配置為非事務方式執行@Transactional(propagation = Propagation.NOT_SUPPORTED)public void processPayment(Long orderId, BigDecimal amount) {paymentMapper.insert(new Payment(orderId, amount));// 若此處發生異常,不會回滾}
}

修復方案

根據業務需求選擇合適的傳播機制,常用的是默認的REQUIRED(如果當前有事務則加入,否則創建新事務)。

修復后代碼

java運行

@Service
public class PaymentService {// 使用默認傳播機制REQUIRED@Transactionalpublic void processPayment(Long orderId, BigDecimal amount) {paymentMapper.insert(new Payment(orderId, amount));}
}

五、同類方法內部調用

失效原理

Spring 事務基于 AOP 代理實現,事務增強邏輯在代理對象中執行。若同一個類中的方法 A 調用方法 B(B 有@Transactional注解),由于調用未經過代理對象,方法 B 的事務注解會失效。

失效代碼

java運行

@Service
public class UserService {// 方法A(無事務)調用方法B(有事務)public void updateUserInfo(Long id, String name, Integer age) {updateUserName(id, name);  // 內部調用,事務失效updateUserAge(id, age);    // 內部調用,事務失效}@Transactionalpublic void updateUserName(Long id, String name) {userMapper.updateName(id, name);}@Transactionalpublic void updateUserAge(Long id, Integer age) {userMapper.updateAge(id, age);}
}

修復方案

方案一:將方法拆分到不同的類中
方案二:通過AopContext獲取代理對象調用

修復后代碼(方案二)

java運行

// 1. 首先在啟動類開啟暴露代理
@SpringBootApplication
@EnableAspectJAutoProxy(exposeProxy = true)  // 關鍵配置
public class Application {public static void main(String[] args) {SpringApplication.run(Application.class, args);}
}// 2. 在Service中通過代理對象調用
@Service
public class UserService {public void updateUserInfo(Long id, String name, Integer age) {// 通過AopContext獲取代理對象UserService proxy = (UserService) AopContext.currentProxy();proxy.updateUserName(id, name);  // 代理對象調用,事務生效proxy.updateUserAge(id, age);    // 代理對象調用,事務生效}@Transactionalpublic void updateUserName(Long id, String name) {userMapper.updateName(id, name);}@Transactionalpublic void updateUserAge(Long id, Integer age) {userMapper.updateAge(id, age);}
}

六、數據庫不支持事務

失效原理

事務最終依賴數據庫支持。若使用的數據庫引擎不支持事務(如 MySQL 的MyISAM引擎),即使代碼中配置了事務,也無法生效。

失效場景

sql

-- 使用MyISAM引擎創建表,不支持事務
CREATE TABLE `user` (`id` bigint NOT NULL AUTO_INCREMENT,`name` varchar(255) DEFAULT NULL,PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8mb4;

此時即使 Service 層配置了@Transactional,數據庫操作也不會有事務保障。

修復方案

使用支持事務的數據庫引擎(如 MySQL 的InnoDB)。

修復后代碼

sql

-- 使用InnoDB引擎創建表,支持事務
CREATE TABLE `user` (`id` bigint NOT NULL AUTO_INCREMENT,`name` varchar(255) DEFAULT NULL,PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

七、未被 Spring 容器管理

失效原理

若事務所在的類未被 Spring 容器掃描并實例化(如未加@Service@Component等注解),@Transactional注解會因沒有代理對象而失效。

失效代碼

java運行

// 未加@Service注解,未被Spring管理
public class ProductService {@Autowiredprivate ProductMapper productMapper;@Transactionalpublic void updateStock(Long productId, Integer quantity) {productMapper.decreaseStock(productId, quantity);}
}

修復方案

為類添加 Spring 注解(如@Service),確保其被 Spring 容器管理。

修復后代碼

java運行

// 添加@Service注解,被Spring容器管理
@Service
public class ProductService {@Autowiredprivate ProductMapper productMapper;@Transactionalpublic void updateStock(Long productId, Integer quantity) {productMapper.decreaseStock(productId, quantity);}
}

八、多線程場景下的事務隔離

失效原理

在事務方法中啟動新線程執行數據庫操作時,新線程的操作不會納入當前事務管理(線程間事務上下文獨立)。即使主線程事務回滾,新線程的操作也可能已提交。

失效代碼

java運行

@Service
public class BatchService {@Autowiredprivate UserMapper userMapper;@Autowiredprivate LogMapper logMapper;@Transactionalpublic void batchProcess(List<Long> userIds) {// 主線程操作userMapper.batchUpdateStatus(userIds, 1);// 新線程執行日志記錄(不在當前事務中)new Thread(() -> {logMapper.insert(new Log("批量處理用戶: " + userIds));}).start();}
}

修復方案

避免在事務方法中使用多線程執行數據庫操作,或使用分布式事務協調機制。

修復后代碼

java運行

@Service
public class BatchService {@Autowiredprivate UserMapper userMapper;@Autowiredprivate LogMapper logMapper;@Transactionalpublic void batchProcess(List<Long> userIds) {// 主線程操作userMapper.batchUpdateStatus(userIds, 1);// 同一事務中執行日志記錄logMapper.insert(new Log("批量處理用戶: " + userIds));}
}

總結

事務失效的核心原因通常與以下幾點相關:

  • 代理機制限制(非 public 方法、同類內部調用)
  • 異常處理不當(捕獲未拋出、未配置 rollbackFor)
  • 事務屬性配置錯誤(傳播機制不合理)
  • 基礎環境問題(數據庫不支持、未被 Spring 管理)
  • 并發場景下的事務隔離問題

在實際開發中,需結合業務場景合理配置事務屬性,同時注意編碼規范,避免上述陷阱,才能確保事務機制有效運行,保障數據一致性。

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

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

相關文章

【Coze搞錢實戰】14. 抖音直播間自動回復機器人實戰教程:三小時搭建智能客服,互動率提升150%(保姆級無代碼指南)

摘要:抖音直播間高頻問題重復回復、觀眾互動不及時是運營痛點。本文針對新手和進階用戶,提供無代碼的自動回復機器人搭建方案:新手1小時完成基礎配置(Coze+抖音對接),進階用戶通過促銷倒計時、粉絲分層、熱點借勢三大策略提升互動率150%。方案基于某女裝直播間實測數據(…

云計算核心知識梳理

云計算作為新一代信息技術的核心,其體系涵蓋特點、定義、技術演進及分類等多個維度,以下是對相關知識的系統整合與解讀。 一、云計算的核心特點 / 優勢 云計算的優勢圍繞資源利用效率、服務靈活性和管理便捷性展開,具體可拆解為五大核心特性: 按需自助服務:用戶無需人工干…

安卓13_ROM修改定制化-----安卓 13 系統 ROM 定制化與低版本系統的核心區別

安卓系統憑借其全球領先的市場占有率,開放特性為廠商和開發者提供了深度定制的空間,形成了豐富的ROM生態圈。從最初的安卓1.0到最新的安卓15,系統在功能、性能和安全方面不斷迭代升級,同時也為ROM定制帶來了新的機遇與挑戰。特別是從安卓11開始,谷歌對系統架構和安全機制進…

【Java后端】Spring Boot 2.7.x 和 Swagger 3.0.x (springfox 3.x) 的兼容性問題

springfox 在 Spring Boot 2.6 開始就有很多兼容性 bug&#xff08;主要是 Spring MVC PathPatternParser 的引入&#xff09;&#xff0c;導致在 Spring Boot 2.6/2.7 里經常出現 無法啟動 / 無法訪問 swagger-ui.html 的情況。&#x1f50e; 問題原因Spring Boot 2.6 開始默認…

Vue3+ts使用oidc-client-ts

配置 OIDC 客戶端 在項目中創建 authOptions 對象&#xff0c;定義 OIDC 認證所需的配置項&#xff1a; export const authOptions {authority: https://xxxxxxxxx/UserCenter, // 認證服務器 URLclient_id: xxxx, // 客戶端 IDredirect_uri: http://localhost:3000/callbac…

從 “數據中轉站“ 到 “邊緣智能中樞“:區域網關的技術突圍與開發范式重構

在物聯網架構中,區域網關長期被視為 "邊緣與云端的橋梁"—— 負責協議轉換、數據轉發、設備接入等基礎功能。但隨著邊緣計算興起與 AI 模型輕量化,區域網關正經歷從 "被動轉發" 到 "主動決策" 的范式躍遷。 本文將從開發視角拆解區域網關的三大…

Django全棧班v1.04 Python基礎語法 20250913 早上

print 函數基本用法 print函數會自加換行符&#xff0c;一個print&#xff0c;會打印一行輸出。 print("第一行") print("第二行") print("第三行")輸出結果&#xff1a;print 輸出多個值 一個print可以同時輸出多個值&#xff0c;這多個值會在一…

面試鴨Java八股之Kafka

Kafka是什么&#xff1f;它的主要應用場景有哪些? Kafka是一種分布式流事件處理平臺&#xff0c;最初由 LinkedIn 開發&#xff0c;現在是 Apache 基金會的一部分。它的核心功能主要包括消息隊列、流處理和數據集成。Kafka以高吞吐量、低延遲、可擴展和高容錯性著稱。 Kafka…

ARM32平臺Bus Error深度排查:從調用棧到硬件原理的完整拆解

ARM32平臺Bus Error深度排查&#xff1a;從調用棧到硬件原理的完整拆解 在嵌入式開發中&#xff0c;Bus Error&#xff08;信號7&#xff09;是個容易讓人頭疼的問題——它不像SIGSEGV&#xff08;段錯誤&#xff09;那樣直觀&#xff0c;常與硬件內存布局、指針破壞等底層問題…

適合工業用的筆記本電腦

在工業領域&#xff0c;生產環境往往復雜多變&#xff0c;從高溫、高濕的車間&#xff0c;到布滿粉塵的礦山&#xff0c;再到震動頻繁的施工現場&#xff0c;普通的筆記本電腦很難在這樣的環境中穩定運行&#xff0c;而工業用筆記本電腦的誕生&#xff0c;完美地解決了這一難題…

在LINUX中常見的文件系統類型

常見文件系統類型對比表文件系統類型作用和特點主要使用場景優缺點ext4Linux標準文件系統&#xff0c;日志式&#xff0c;支持大文件和分區Linux根文件系統、/home、/var等主要分區優點&#xff1a;穩定成熟&#xff0c;支持大文件(16TB)&#xff0c;日志功能保證數據安全&…

Unity核心概念⑥:Time

一、Time的主要用途主要用于游戲中參與位移、記時、時間暫停等。二、時間縮放比例1.時間停止&#xff1a;Time.timeScale 0;2.回復正常&#xff1a;Time.timeScale 1;3.二倍速&#xff1a;Time.timeScale 2;三、幀間隔時間幀間隔時間是指最近的一幀用了多少時間。1.用途主要…

Node.js 模塊化規范詳解

在 Node.js 中&#xff0c;模塊化是開發應用程序的核心概念&#xff0c;它使得代碼可以按照功能模塊進行分割&#xff0c;易于維護、復用和擴展。Node.js 支持兩種模塊化規范&#xff1a;CommonJS&#xff08;CJS&#xff09;&#xff1a;這是 Node.js 最初使用的模塊化規范。E…

前端網絡性能優化實踐:從 HTTP 請求到 HTTPS 與 HTTP/2 升級

在前端性能優化體系中&#xff0c;服務端與網絡層的優化是提升用戶體驗的關鍵環節。本文將圍繞 HTTP 請求優化、Cookie 管理、服務器緩存配置、gzip 壓縮、HTTPS 部署及 HTTP/2 升級等核心內容&#xff0c;系統拆解優化策略與實施方法&#xff0c;為團隊技術分享提供完整的知識…

[數據結構——lesson8.樹]

目錄 引言 學習目標 1.樹的概念及結構 1.1樹的定義 1.2樹的基本概念 1.3 樹的表示 (1)雙親表示法 (2)孩子表示法 (3)左孩子右兄弟表示法 1.4 樹在實際中的運用&#xff08;表示文件系統的目錄樹結構&#xff09; 結束語&#xff1a; 引言 之前我們學習了棧和隊列數…

告別雙系統——WSL2+UBUNTU在WIN上暢游LINUX

在Windows 11上配置WSL開發環境指南 最近換工作需要深入研究代碼&#xff0c;發現WSL&#xff08;Windows Subsystem for Linux&#xff09;是微軟為Windows開發者提供的強大工具&#xff0c;可以在Windows上直接運行Ubuntu子系統&#xff0c;無需雙系統或虛擬機&#xff08;滿…

Python爬蟲實戰:研究Ticks and spines模塊,構建電商數據采集和分析系統

1. 引言 1.1 研究背景 在信息時代,互聯網數據呈現爆炸式增長,涵蓋社會、經濟、文化等多個領域,具有極高的研究與應用價值。如何高效獲取目標數據并進行深度分析,成為信息處理領域的重要課題。Python 憑借其豐富的庫支持和簡潔的語法,在數據爬取與分析領域得到廣泛應用:…

前端基礎 —— B / CSS基礎

一、CSS 基礎概述定義&#xff1a;層疊樣式表&#xff08;Cascading Style Sheets&#xff09;作用&#xff1a;美化頁面、實現樣式與結構分離二、CSS 基本語法與引入方式1. 語法規范選擇器 {一條/N條聲明}選擇器決定針對誰修改 (找誰) 聲明決定修改啥. (干啥)<style> p…

智能農機無人駕駛作業套圈路徑規劃

國產輕量級桌面GIS軟件Snaplayers實踐&#xff1a;智能農機無人駕駛作業套圈路徑規劃1、選擇地塊角點坐標文件2、加載地塊到地圖中3、設置套圈作業路徑規劃參數4、生成套圈作業路徑5、查看套圈路徑6、查看套圈路徑8、完成本算法已經在國內外等農場已經使用多年。Snaplayers研發…

Java Collection集合框架:體系、核心與選型

目錄 一、集合框架的頂層設計&#xff1a;接口與層次 1. 兩大核心接口&#xff1a;Collection 和 Map 2. Collection接口的三大派系 二、核心實現類詳解 1. List家族實現 2. Set家族實現 3. Queue/Deque家族實現 PriorityQueue&#xff1a; ArrayDeque&#xff1a; 三…