一、什么是事務回滾?
事務回滾指的是:當執行過程中發生異常時,之前對數據庫所做的更改全部撤銷,數據庫狀態恢復到事務開始前的狀態。這是數據庫“原子性”原則的體現。
二、Spring 中的 @Transactional
默認行為
在 Spring 中,使用注解方式開啟事務非常簡單:
@Transactional
public void doSomething() {// 執行數據庫操作
}
此時的默認行為是:
- 事務會在方法成功執行后提交;
- 遇到
RuntimeException
或Error
,會自動回滾; - 遇到
Checked Exception
(即編譯時異常),不會自動回滾。
例如:
@Transactional
public void test1() {throw new RuntimeException(); // ? 會回滾
}@Transactional
public void test2() throws Exception {throw new Exception(); // ? 不會回滾
}
三、使用 rollbackFor
讓事務回滾受檢異常
如果你希望事務在任何異常發生時都回滾,包括受檢異常,比如 IOException
、SQLException
,就需要顯式指定:
@Transactional(rollbackFor = Exception.class)
public void test3() throws Exception {throw new Exception(); // ? 會回滾
}
rollbackFor
的值可以是一個或多個異常類;- 你可以根據需要選擇只對某些異常類型回滾,其他的則不回滾。
四、rollbackFor
和 rollbackOn
的區別
特性 | 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("測試受檢異常");
}
注意:使用的是不同的注解類,不能混用!
五、常見誤區
? 誤區1:以為所有異常都會觸發事務回滾
Spring 默認只回滾 RuntimeException
,不會回滾 Exception
(受檢異常)。這是導致事務未回滾的最常見原因。
? 誤區2:以為 @Transactional
可以應用于任何方法
只有被 Spring 容器管理(即被 Spring 掃描并代理)的類中的 public
方法,@Transactional
才有效。如果你在 private
方法上加了注解,是不會生效的。
? 誤區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 | 不回滾任何異常 |
控制參數 | rollbackFor , noRollbackFor 等 | rollbackOn , dontRollbackOn |
常見場景 | Spring Boot, Spring MVC 項目 | Java EE, Jakarta EE 應用服務器項目 |
建議用法 | 用 Spring 的事務注解為主 | 僅在 Java EE 項目中使用 |
七、結語
事務控制是保障系統數據一致性的重要手段,理解事務的回滾機制尤為重要。在實際開發中,推薦明確指定異常回滾策略,避免因受檢異常不回滾而造成數據異常。
希望這篇文章能幫你在開發中更精準地使用 @Transactional
,寫出更健壯、可控的代碼。如果你有更多問題,歡迎留言討論!