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)文章
SpringBoot項(xiàng)目jar發(fā)布后如何獲取jar包所在目錄路徑
這篇文章主要介紹了SpringBoot項(xiàng)目jar發(fā)布后如何獲取jar包所在目錄路徑,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-11-11
Java實(shí)現(xiàn)隨機(jī)生成大小寫(xiě)混合的卡密的步驟
在現(xiàn)代軟件開(kāi)發(fā)中,生成隨機(jī)卡密是一個(gè)常見(jiàn)的需求,尤其是在需要為用戶(hù)生成唯一識(shí)別碼或安全令牌的場(chǎng)景中,卡密通常由數(shù)字和字母組成,有時(shí)還會(huì)包含特殊字符,本文通過(guò)代碼講解的非常詳細(xì),需要的朋友可以參考下2024-11-11
SpringMVC中RequestContextHolder獲取請(qǐng)求信息的方法
這篇文章主要介紹了SpringMVC中RequestContextHolder獲取請(qǐng)求信息的方法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-04-04
Java中使用@CrossOrigin和Proxy解決跨域問(wèn)題詳解
這篇文章主要介紹了Java中使用@CrossOrigin和Proxy解決跨域問(wèn)題詳解,在Web開(kāi)發(fā)中,如果前端頁(yè)面和后端接口不在同一個(gè)域名下,就會(huì)發(fā)生跨域請(qǐng)求的問(wèn)題,同源策略是瀏覽器的一種安全策略,它限制了來(lái)自不同源的客戶(hù)端腳本在瀏覽器中運(yùn)行時(shí)的交互,需要的朋友可以參考下2023-12-12
在Java的Struts中判斷是否調(diào)用AJAX及用攔截器對(duì)其優(yōu)化
這篇文章主要介紹了在Java的Struts中判斷是否調(diào)用AJAX及用攔截器對(duì)其優(yōu)化的方法,Struts框架是Java的SSH三大web開(kāi)發(fā)框架之一,需要的朋友可以參考下2016-01-01
MyBatis/mybatis-plus項(xiàng)目打印SQL的方法實(shí)現(xiàn)
SpringBoot項(xiàng)目中,經(jīng)常需要打印SQL語(yǔ)句及其參數(shù),本文就來(lái)介紹一下MyBatis/mybatis-plus項(xiàng)目打印SQL的方法實(shí)現(xiàn),具有一定的參考價(jià)值,感興趣的可以了解一下2024-07-07
SpringCloud及Nacos服務(wù)注冊(cè)IP選擇問(wèn)題解決方法
這篇文章主要介紹了SpringCloud及Nacos服務(wù)注冊(cè)IP選擇問(wèn)題,為什么注冊(cè)的IP和真實(shí)IP不符合呢,原因是Nacos客戶(hù)端在注冊(cè)服務(wù)時(shí)會(huì)從機(jī)器網(wǎng)卡中選擇一個(gè)IP來(lái)注冊(cè),所以,當(dāng)注冊(cè)了的是非真實(shí)IP后,另一臺(tái)機(jī)器調(diào)用時(shí)是不可能調(diào)通的,知道問(wèn)題原因就是解決方法,一起看看吧2024-01-01
Java 是如何讀取和寫(xiě)入瀏覽器Cookies的實(shí)例詳解
這篇文章主要介紹了Java 是如何讀取和寫(xiě)入瀏覽器Cookies的實(shí)例的相關(guān)資料,需要的朋友可以參考下2016-09-09
SSH框架網(wǎng)上商城項(xiàng)目第13戰(zhàn)之Struts2文件上傳功能
這篇文章主要為大家詳細(xì)介紹了SSH框架網(wǎng)上商城項(xiàng)目第13戰(zhàn)之Struts2文件上傳功能的相關(guān)資料,感興趣的小伙伴們可以參考一下2016-06-06

