首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 綜合教學

深入解析 Spring 事務傳播機制:從 REQUIRED 到 NESTED 的核心差異

     編輯:Java 綜合教學

Spring 事務傳播行為全覽

Spring 框架透過 Propagation 列舉定義了七種事務傳播行為,掌握它們是正確配置事務邊界的基礎:

  • PROPAGATION_REQUIRED:最常用的選項。若當前存在事務則加入,否則新建一個。
  • PROPAGATION_SUPPORTS:支持當前事務,無事務時以非事務方式執行。
  • PROPAGATION_MANDATORY:強制要求存在事務,否則拋出異常。
  • PROPAGATION_REQUIRES_NEW:總是開啟一個全新的獨立事務,若有現有事務則掛起。
  • PROPAGATION_NOT_SUPPORTED:以非事務方式運行,掛起現有事務。
  • PROPAGATION_NEVER:非事務方式運行,若有事務則拋出異常。
  • PROPAGATION_NESTED:若有事務則在巢狀事務中執行(使用 Savepoint),無事務時等同 REQUIRED。

前六種對應 EJB CMT 規格,而 PROPAGATION_NESTED 是 Spring 獨有的進階特性,依賴底層事務管理器支援 JDBC 3.0 Savepoint API(如 DataSourceTransactionManager)。

常見誤區:服務層互調不需 NESTED

許多開發者誤以為 ServiceA 調用 ServiceB 時,內層方法必須設為 NESTED。實際上,若兩者均配置 REQUIRED,內層方法會自然加入外層事務。若內層拋出異常且外層未特別配置不回滾該異常(如 +MyCheckedException),整個事務仍會回滾。「Service 只能呼叫 DAO」的說法純屬無稽之談,Spring 僅攔截配置了事務屬性的方法,不關心其所在層級。

真正的巢狀事務:REQUIRES_NEW vs NESTED

Juergen Hoeller(Spring 核心開發者)曾詳細闡述兩者本質區別:

PROPAGATION_REQUIRES_NEW:完全獨立的內部事務

  • 擁有獨立的隔離級別、鎖資源。
  • 外部事務在內部事務執行期間被掛起。
  • 內部事務提交或回滾不影響外部事務。
  • 典型應用:ID 生成器存取序列表,需極短鎖定時間,避免阻塞長時間運行的外部事務。

PROPAGATION_NESTED:真正的子事務

  • 屬於外部事務的一部分,僅在外部事務提交時一併提交。
  • 啟動時設定 Savepoint,失敗時回滾至該 Savepoint。
  • 允許在同一個隔離事務中嘗試多個執行子路徑:某分支失敗則回滾至分支起始點,繼續嘗試其他分支或主流程,不會損失外部事務已完成的工作。
  • 經典場景:批次解析大型轉帳檔案,整個檔案在單一事務中提交,但單筆區塊失敗時僅回滾該區塊操作,保留前序成功處理的資料,極大提升效率。

外部事務如何利用 NESTED 的 Savepoint 特性

關鍵在於異常處理策略:

// ServiceA 修改為捕獲內層異常,執行替代邏輯
void methodA() {
    try {
        ServiceB.methodB(); // 配置 PROPAGATION_NESTED
    } catch (SomeException e) {
        // 內層已回滾至 Savepoint,此處可執行 ServiceC.methodC() 等補償操作
        ServiceC.methodC();
    }
}

若不捕獲異常,異常向上傳播至外部事務邊界,由外部事務的回滾規則決定是否回滾整個事務。

Spring 中啟用 PROPAGATION_NESTED 的條件

  1. 事務管理器屬性:必須將 nestedTransactionAllowed 設為 true(預設為 false)。
  2. JDK 版本:需 1.4+(支援 java.sql.Savepoint)。
  3. JDBC 驅動:Connection.getMetaData().supportsSavepoints() 必須返回 true(即支援 JDBC 3.0)。

底層實現在 AbstractPlatformTransactionManager.handleExistingTransaction 中:檢測到 PROPAGATION_NESTED 時,若允許巢狀事務且使用 Savepoint 機制,則建立 DefaultTransactionStatus 並呼叫 createAndHoldSavepoint(),最終委託 JdbcTransactionObjectSupport 透過 JDBC 3.0 API 建立 Savepoint。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved