SpringBoot事務(wù)失效的七種場(chǎng)景分析及解決方案
事務(wù)失效場(chǎng)景1:方法非public修飾
原因
Spring事務(wù)基于動(dòng)態(tài)代理(AOP)實(shí)現(xiàn),非public方法無(wú)法被代理攔截,導(dǎo)致事務(wù)失效。
代碼示例
@Service
public class OrderService {
@Transactional
private void createOrder() { // 非public方法
// 業(yè)務(wù)邏輯
}
}
解決方案
- 將方法改為
public修飾。 - 若需限制方法訪問(wèn)權(quán)限,可通過(guò)編程式事務(wù)(
TransactionTemplate)實(shí)現(xiàn)。
事務(wù)失效場(chǎng)景2:自調(diào)用問(wèn)題
原因
同類中方法A調(diào)用方法B(帶@Transactional),由于代理機(jī)制失效,事務(wù)不生效。
代碼示例
@Service
public class UserService {
public void updateUser() {
this.saveUser(); // 自調(diào)用
}
@Transactional
public void saveUser() {
// 數(shù)據(jù)庫(kù)操作
}
}
解決方案
- 將事務(wù)方法拆分到另一個(gè)類中,通過(guò)注入調(diào)用。
- 使用
AopContext.currentProxy()獲取代理對(duì)象(需開(kāi)啟exposeProxy)。
事務(wù)失效場(chǎng)景3:異常類型未被捕獲
原因
默認(rèn)僅對(duì)RuntimeException和Error回滾,若拋出其他異常(如IOException)且未配置rollbackFor,事務(wù)不會(huì)回滾。
代碼示例
@Transactional
public void processData() throws IOException {
// 拋出IOException
throw new IOException("文件異常");
}
解決方案
- 明確指定回滾異常類型:
@Transactional(rollbackFor = Exception.class)
事務(wù)失效場(chǎng)景4:事務(wù)傳播行為配置錯(cuò)誤
原因
例如REQUIRES_NEW嵌套使用時(shí),內(nèi)層事務(wù)失敗可能不影響外層事務(wù)。
代碼示例
@Transactional(propagation = Propagation.REQUIRED)
public void outerMethod() {
innerMethod(); // 內(nèi)層事務(wù)獨(dú)立提交
}
@Transactional(propagation = Propagation.REQUIRES_NEW)
public void innerMethod() {
// 操作失敗但outerMethod繼續(xù)執(zhí)行
}
解決方案
- 根據(jù)業(yè)務(wù)需求調(diào)整傳播行為,如改為
REQUIRED。 - 避免過(guò)度嵌套事務(wù)。
事務(wù)失效場(chǎng)景5:多數(shù)據(jù)源未指定事務(wù)管理器
原因
多數(shù)據(jù)源環(huán)境下未明確指定transactionManager,導(dǎo)致事務(wù)綁定到默認(rèn)管理器。
代碼示例
@Transactional // 默認(rèn)使用primary事務(wù)管理器
public void saveToSecondaryDB() {
// 操作secondary數(shù)據(jù)源
}
解決方案
- 注解中指定事務(wù)管理器:
@Transactional("secondaryTransactionManager")
事務(wù)失效場(chǎng)景6:手動(dòng)捕獲異常未拋出
原因
捕獲異常后未重新拋出,事務(wù)攔截器無(wú)法觸發(fā)回滾。
代碼示例
@Transactional
public void updateOrder() {
try {
// 數(shù)據(jù)庫(kù)操作
} catch (Exception e) {
log.error("錯(cuò)誤", e); // 未拋出異常
}
}
解決方案
- 在
catch塊中拋出RuntimeException。 - 或使用
TransactionAspectSupport.currentTransactionStatus().setRollbackOnly()手動(dòng)回滾。
事務(wù)失效場(chǎng)景7:非事務(wù)方法調(diào)用事務(wù)方法
原因
若父類方法未開(kāi)啟事務(wù),調(diào)用子類@Transactional方法時(shí),代理失效。
代碼示例
public class BaseService {
public void execute() {
save(); // 事務(wù)失效
}
@Transactional
public void save() {}
}
解決方案
- 將事務(wù)注解添加到父類方法。
- 避免通過(guò)繼承層級(jí)調(diào)用事務(wù)方法。
總結(jié)
- 檢查方法修飾符和代理機(jī)制。
- 確保異常類型和傳播行為匹配業(yè)務(wù)需求。
- 多數(shù)據(jù)源需顯式指定事務(wù)管理器。
- 優(yōu)先通過(guò)設(shè)計(jì)規(guī)避自調(diào)用問(wèn)題。
以上就是SpringBoot事務(wù)失效的七種場(chǎng)景分析及解決方案的詳細(xì)內(nèi)容,更多關(guān)于SpringBoot事務(wù)失效場(chǎng)景的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Java深入學(xué)習(xí)圖形用戶界面GUI之事件處理
這篇文章主要介紹了基于Java GUI 事件處理方式,一個(gè)圖形界面制作完成了,在程序開(kāi)發(fā)中只是完成了起步的工作。要想讓一個(gè)組件都發(fā)揮自己的作用.就必須對(duì)所有的組件進(jìn)行事件處理2022-05-05
詳解Spring Cloud Alibaba Sidecar多語(yǔ)言微服務(wù)異構(gòu)
這篇文章主要介紹了詳解Spring Cloud Alibaba Sidecar多語(yǔ)言微服務(wù)異構(gòu),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-11-11
SpringBoot整合POI實(shí)現(xiàn)Excel文件讀寫操作
EasyExcel是一個(gè)基于Java的、快速、簡(jiǎn)潔、解決大文件內(nèi)存溢出的Excel處理工具,這篇文章主要介紹了SpringBoot整合POI實(shí)現(xiàn)Excel文件讀寫操作,首先準(zhǔn)備環(huán)境進(jìn)行一系列操作,本文給大家介紹的非常詳細(xì),需要的朋友參考下吧2023-10-10
Java集合源碼ArrayList的可視化操作過(guò)程示例詳解
這篇文章主要介紹了Java集合源碼ArrayList的可視化操作過(guò)程示例詳解,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友參考下吧2025-06-06
SpringBoot詳細(xì)講解靜態(tài)資源導(dǎo)入的實(shí)現(xiàn)
在Web開(kāi)發(fā)過(guò)程中,我們需要接觸許多靜態(tài)資源,如CSS、JS、圖片等;在之前的開(kāi)發(fā)中,這些資源都放在Web目錄下,用到的時(shí)候按照對(duì)應(yīng)路徑訪問(wèn)即可。不過(guò)在SpringBoot項(xiàng)目中,沒(méi)有了Web目錄,那這些靜態(tài)資源該放到哪里去,又要如何訪問(wèn)呢?這就是我們要講的靜態(tài)資源導(dǎo)入2022-05-05
Java對(duì)List進(jìn)行排序的方法總結(jié)
在Java中,對(duì)List進(jìn)行排序是一項(xiàng)常見(jiàn)的任務(wù),Java提供了多種方法來(lái)對(duì)List中的元素進(jìn)行排序,本文將詳細(xì)介紹如何使用Java來(lái)實(shí)現(xiàn)List的排序操作,涵蓋了常用的排序方法和技巧,需要的朋友可以參考下2024-07-07

