Java事務回滾詳解以及常見誤區(qū)
一、什么是事務回滾?
事務回滾指的是:當執(zhí)行過程中發(fā)生異常時,之前對數(shù)據(jù)庫所做的更改全部撤銷,數(shù)據(jù)庫狀態(tài)恢復到事務開始前的狀態(tài)。這是數(shù)據(jù)庫“原子性”原則的體現(xiàn)。
二、Spring 中的@Transactional默認行為
在 Spring 中,使用注解方式開啟事務非常簡單:
@Transactional
public void doSomething() {
// 執(zhí)行數(shù)據(jù)庫操作
}
此時的默認行為是:
- 事務會在方法成功執(zhí)行后提交;
- 遇到 RuntimeException 或 Error,會自動回滾;
- 遇到 Checked Exception(即編譯時異常),不會自動回滾。
例如:
@Transactional
public void test1() {
throw new RuntimeException(); // ? 會回滾
}
@Transactional
public void test2() throws Exception {
throw new Exception(); // ? 不會回滾
}
三、使用rollbackFor讓事務回滾受檢異常
如果你希望事務在任何異常發(fā)生時都回滾,包括受檢異常,比如 IOException、SQLException,就需要顯式指定:
@Transactional(rollbackFor = Exception.class)
public void test3() throws Exception {
throw new Exception(); // ? 會回滾
}
rollbackFor的值可以是一個或多個異常類;- 你可以根據(jù)需要選擇只對某些異常類型回滾,其他的則不回滾。
四、rollbackFor和rollbackOn的區(qū)別
| 特性 | rollbackFor | rollbackOn |
|---|---|---|
| 適用范圍 | Spring | Java EE / JTA |
| 包名 | org.springframework.transaction.annotation.Transactional | javax.transaction.Transactional |
| 默認行為 | 回滾RuntimeException | 不回滾任何異常 |
| 明確配置后 | 可回滾任何指定異常 | 可回滾任何指定異常 |
示例比較:
Spring 中的寫法:
import org.springframework.transaction.annotation.Transactional;
@Transactional(rollbackFor = Exception.class)
public void springTransaction() throws Exception {
throw new Exception("測試受檢異常");
}
JTA(Java EE)中的寫法:
import javax.transaction.Transactional;
@Transactional(rollbackOn = Exception.class)
public void jtaTransaction() throws Exception {
throw new Exception("測試受檢異常");
}
注意:使用的是不同的注解類,不能混用!
五、常見誤區(qū)
? 誤區(qū)1:以為所有異常都會觸發(fā)事務回滾
Spring 默認只回滾 RuntimeException,不會回滾 Exception(受檢異常)。這是導致事務未回滾的最常見原因。
? 誤區(qū)2:以為@Transactional可以應用于任何方法
只有被 Spring 容器管理(即被 Spring 掃描并代理)的類中的 public 方法,@Transactional 才有效。如果你在 private 方法上加了注解,是不會生效的。
? 誤區(qū)3:使用錯誤的注解類
Spring 和 JTA 的 @Transactional 注解來自不同的包,使用時務必導入正確:
- Spring:
org.springframework.transaction.annotation.Transactional - JTA:
javax.transaction.Transactional
六、小結
常見問題與解決方式
| 問題 | 默認行為 | 解決方式 |
|---|---|---|
| 事務不回滾受檢異常 | ? 不回滾 | ? 添加rollbackFor = Exception.class(Spring)或 rollbackOn = Exception.class(JTA) |
| 事務注解不生效 | ? 方法不是public,類未被 Spring 管理 | ? 保證類被 Spring 掃描,方法為public |
| 導入錯誤注解 | ? 使用了錯誤的@Transactional 注解 | ? 使用正確包名下的注解(見下表) |
Spring 與 JTA 的@Transactional對比
| 特性 | Spring | JTA(Java EE) |
|---|---|---|
| 注解類全名 | org.springframework.transaction.annotation.Transactional | javax.transaction.Transactional |
| 默認回滾行為 | 回滾RuntimeException,不回滾 Exception | 不回滾任何異常 |
| 控制參數(shù) | rollbackFor, noRollbackFor 等 | rollbackOn, dontRollbackOn |
| 常見場景 | Spring Boot, Spring MVC 項目 | Java EE, Jakarta EE 應用服務器項目 |
| 建議用法 | 用 Spring 的事務注解為主 | 僅在 Java EE 項目中使用 |
七、結語
事務控制是保障系統(tǒng)數(shù)據(jù)一致性的重要手段,理解事務的回滾機制尤為重要。在實際開發(fā)中,推薦明確指定異?;貪L策略,避免因受檢異常不回滾而造成數(shù)據(jù)異常。
希望這篇文章能幫你在開發(fā)中更精準地使用 @Transactional,寫出更健壯、可控的代碼。
附:下面說說我經常見到的3種事務不回滾的產生原因:
(1)聲明式事務配置切入點表達式寫錯了,沒切中Service中的方法
(2)Service方法中,把異常給try catch了,但catch里面只是打印了異常信息,沒有手動拋出RuntimeException異常
(3)Service方法中,拋出的異常不屬于運行時異常(如IO異常),因為Spring默認情況下是捕獲到運行時異常就回滾
到此這篇關于Java事務回滾詳解以及常見誤區(qū)的文章就介紹到這了,更多相關Java事務回滾內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
教你用springboot連接mysql并實現(xiàn)增刪改查
今天教各位小伙伴用springboot連接mysql并實現(xiàn)增刪改查功能,文中有非常詳細的步驟及代碼示例,對正在學習Java的小伙伴們有非常好的幫助,需要的朋友可以參考下2021-05-05
SpringBoot讀取resource目錄下文件失敗的原因及解決方案
在idea中運行時,有些resource下文件讀取工具類能夠正常獲取讀取到文件,但是通過java–jar的方式去運行jar包,此時resource下文件讀取工具類讀取文件就失效了,本文就給大家介紹一下SpringBoot讀取resource目錄下文件失敗解決方案,需要的朋友可以參考下2023-08-08
JAVA CountDownLatch與thread-join()的區(qū)別解析
這篇文章主要介紹了JAVA CountDownLatch與thread-join()的區(qū)別解析,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下2019-08-08
Spring源碼BeanFactoryPostProcessor詳解
BeanFactoryPostProcessor的執(zhí)行時機是在Spring掃描完成后,Bean初始化前,當我們實現(xiàn)BeanFactoryPostProcessor接口,可以在Bean的初始化之前對Bean進行屬性的修改,下面通過本文看下Spring源碼分析-BeanFactoryPostProcessor的實例代碼,感興趣的朋友一起看看吧2021-11-11

