SpringBoot事務(wù)失效問(wèn)題原因、場(chǎng)景與解決方案
一、事務(wù)失效的常見(jiàn)場(chǎng)景
1.1 同類(lèi)中方法直接調(diào)用導(dǎo)致事務(wù)失效
原因分析:
Spring 的事務(wù)是通過(guò) AOP 代理實(shí)現(xiàn)的,只有通過(guò)代理對(duì)象調(diào)用的方法,事務(wù)才會(huì)生效。如果在同一個(gè)類(lèi)中,一個(gè)方法直接調(diào)用另一個(gè)帶有 @Transactional 注解的方法(即 this.method() 方式),則事務(wù)不會(huì)生效。
示例代碼:
@Service
public class UserService {
@Transactional
public void createUser(User user) {
// 保存用戶(hù)
}
public void createUserAndLog(User user) {
this.createUser(user); // 事務(wù)失效
log.info("用戶(hù)創(chuàng)建成功");
}
}
解決方案:
- 將事務(wù)方法提取到另一個(gè)類(lèi)中,通過(guò) Spring 注入調(diào)用。
- 使用
AopContext.currentProxy()獲取當(dāng)前代理對(duì)象調(diào)用方法。 - 自我注入:將當(dāng)前 Service 注入到自身,通過(guò)注入的對(duì)象調(diào)用方法。
推薦方式(自我注入):
@Service
public class UserService {
@Autowired
private UserService self; // 自我注入
@Transactional
public void createUser(User user) {
// 保存用戶(hù)
}
public void createUserAndLog(User user) {
self.createUser(user); // 事務(wù)生效
log.info("用戶(hù)創(chuàng)建成功");
}
}
1.2 異常未被正確捕獲或拋出
原因分析:
默認(rèn)情況下,Spring 只對(duì) RuntimeException 和 Error 進(jìn)行回滾。如果捕獲了異常但未拋出,或拋出了非運(yùn)行時(shí)異常,事務(wù)不會(huì)回滾。
示例代碼:
@Transactional
public void updateUser(User user) {
try {
userRepository.save(user);
} catch (Exception e) {
log.error("更新失敗", e);
// 異常被吞掉,事務(wù)不會(huì)回滾
}
}
解決方案:
- 在
@Transactional注解中指定回滾的異常類(lèi)型。 - 捕獲異常后,重新拋出 RuntimeException。
推薦方式:
@Transactional(rollbackFor = Exception.class)
public void updateUser(User user) {
try {
userRepository.save(user);
} catch (Exception e) {
log.error("更新失敗", e);
throw new RuntimeException("更新失敗", e);
}
}
1.3 事務(wù)傳播行為配置不當(dāng)
原因分析:
在嵌套事務(wù)中,如果內(nèi)層事務(wù)使用了 Propagation.REQUIRES_NEW,它會(huì)啟動(dòng)一個(gè)獨(dú)立的新事務(wù),外層事務(wù)的回滾不會(huì)影響內(nèi)層事務(wù),可能導(dǎo)致數(shù)據(jù)不一致。
示例代碼:
@Transactional(propagation = Propagation.REQUIRES_NEW)
public void innerMethod() {
// 內(nèi)層事務(wù)
}
@Transactional
public void outerMethod() {
innerMethod();
throw new RuntimeException("外層異常");
}
問(wèn)題:
- 外層事務(wù)回滾,但內(nèi)層事務(wù)已提交,導(dǎo)致數(shù)據(jù)不一致。
解決方案:
- 根據(jù)業(yè)務(wù)需求選擇合適的傳播行為。
- 如果希望內(nèi)外事務(wù)一致,避免使用
REQUIRES_NEW,改用REQUIRED。
推薦方式:
@Transactional(propagation = Propagation.REQUIRED)
public void innerMethod() {
// 內(nèi)層事務(wù)
}
@Transactional
public void outerMethod() {
innerMethod();
throw new RuntimeException("外層異常");
}
1.4 數(shù)據(jù)庫(kù)引擎不支持事務(wù)
原因分析:
某些數(shù)據(jù)庫(kù)引擎(如 MySQL 的 MyISAM)不支持事務(wù),即使代碼中配置了事務(wù),也不會(huì)生效。
解決方案:
- 確保數(shù)據(jù)庫(kù)使用支持事務(wù)的引擎,如 InnoDB。
1.5 事務(wù)管理器未正確配置
原因分析:
如果項(xiàng)目中沒(méi)有正確配置事務(wù)管理器,@Transactional 注解不會(huì)生效。
解決方案:
- 確保在配置類(lèi)中配置了事務(wù)管理器,例如:
@Bean
public PlatformTransactionManager transactionManager(DataSource dataSource) {
return new DataSourceTransactionManager(dataSource);
}
1.6 多數(shù)據(jù)源事務(wù)管理問(wèn)題
原因分析:
在多數(shù)據(jù)源場(chǎng)景下,如果沒(méi)有為每個(gè)數(shù)據(jù)源配置獨(dú)立的事務(wù)管理器,事務(wù)可能會(huì)失效。
解決方案:
- 為每個(gè)數(shù)據(jù)源配置獨(dú)立的事務(wù)管理器。
- 使用
@Transactional(value = "transactionManagerName")指定事務(wù)管理器。
二、如何排查事務(wù)失效問(wèn)題
2.1 啟用事務(wù)日志
在 application.properties 中開(kāi)啟事務(wù)日志:
logging.level.org.springframework.transaction=DEBUG logging.level.org.springframework.jdbc=DEBUG
2.2 檢查代理對(duì)象
確保事務(wù)方法是通過(guò) Spring 的代理對(duì)象調(diào)用的,而不是直接調(diào)用。
2.3 檢查異常處理
確保異常被正確拋出,并符合事務(wù)回滾的條件。
2.4 檢查數(shù)據(jù)庫(kù)引擎
確保數(shù)據(jù)庫(kù)引擎支持事務(wù),例如使用 InnoDB。
三、事務(wù)傳播行為(Propagation)的常用類(lèi)型
| 傳播行為類(lèi)型 | 說(shuō)明 |
|---|---|
| REQUIRED(默認(rèn)) | 當(dāng)前方法加入已有事務(wù),若沒(méi)有則創(chuàng)建新事務(wù)。 |
| REQUIRES_NEW | 創(chuàng)建新事務(wù),并掛起當(dāng)前事務(wù)。 |
| NOT_SUPPORTED | 不支持事務(wù),掛起當(dāng)前事務(wù)。 |
| NEVER | 不允許事務(wù),若當(dāng)前有事務(wù)則拋出異常。 |
| SUPPORTS | 當(dāng)前方法可以在事務(wù)中執(zhí)行,也可以不在事務(wù)中執(zhí)行。 |
| MANDATORY | 當(dāng)前方法必須在事務(wù)中執(zhí)行,若沒(méi)有事務(wù)則拋出異常。 |
四、總結(jié)
Spring Boot 中的事務(wù)失效問(wèn)題,通常是由于以下原因?qū)е碌模?/p>
- 同類(lèi)中方法直接調(diào)用。
- 異常未被正確拋出。
- 事務(wù)傳播行為配置不當(dāng)。
- 數(shù)據(jù)庫(kù)引擎不支持事務(wù)。
- 事務(wù)管理器未正確配置。
- 多數(shù)據(jù)源事務(wù)管理問(wèn)題。
為了避免事務(wù)失效,建議遵循以下最佳實(shí)踐:
- 確保事務(wù)方法通過(guò) Spring 代理調(diào)用。
- 正確處理異常,確保事務(wù)回滾。
- 合理配置事務(wù)傳播行為。
- 使用支持事務(wù)的數(shù)據(jù)庫(kù)引擎。
- 正確配置事務(wù)管理器。
通過(guò)本文的分析和解決方案,相信大家對(duì) Spring Boot 的事務(wù)管理有了更深入的理解。在實(shí)際開(kāi)發(fā)中,合理使用事務(wù),能夠有效保證數(shù)據(jù)的一致性和完整性。
以上就是SpringBoot事務(wù)失效問(wèn)題原因、場(chǎng)景與解決方案的詳細(xì)內(nèi)容,更多關(guān)于SpringBoot事務(wù)失效問(wèn)題的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
使用Maven和SpringBoot搭建客戶(hù)數(shù)據(jù)清洗項(xiàng)目框架
這篇文章主要為大家詳細(xì)介紹了如何使用Maven和SpringBoot搭建客戶(hù)數(shù)據(jù)清洗項(xiàng)目框架,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以了解一下2025-07-07
Java?WorkBook對(duì)Excel的基本操作方法
這篇文章主要介紹了Java?WorkBook對(duì)Excel的基本操作方法,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2023-03-03
SpringBoot 動(dòng)態(tài)定時(shí)器的使用方法
這篇文章主要介紹了SpringBoot 動(dòng)態(tài)定時(shí)器的使用方法,非常不錯(cuò),具有一定的參考借鑒借鑒價(jià)值,需要的朋友可以參考下2018-05-05
java文件/圖片的上傳與下載以及MultipartFile詳解
文章介紹了MultipartFile類(lèi)的使用,包括獲取文件名、文件類(lèi)型、文件大小等方法,以及如何處理多文件上傳和文件大小限制,同時(shí)提供了文件上傳和下載的示例代碼2025-02-02
Java數(shù)據(jù)結(jié)構(gòu)之順序表的實(shí)現(xiàn)
線性表(linear?list)是n個(gè)具有相同特性的數(shù)據(jù)元素的有限序列。順序表是常見(jiàn)的線性表之一,本文將詳細(xì)講講順序表的原理與實(shí)現(xiàn),需要的可以參考一下2022-08-08
Java中EasyPoi導(dǎo)出復(fù)雜合并單元格的方法
這篇文章主要介紹了Java中EasyPoi導(dǎo)出復(fù)雜合并單元格的方法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2021-01-01
Spring Security中的Servlet過(guò)濾器體系代碼分析
這篇文章主要介紹了Spring Security中的Servlet過(guò)濾器體系,本文通過(guò)圖文并茂的形式給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-07-07

