回滾宣告式事務
上一節概述瞭如何為應用程式中的類(通常是服務層類)宣告式地指定事務設定的基本知識。本節描述瞭如何在 XML 配置中以簡單、宣告式的方式控制事務回滾。有關使用 @Transactional 註解宣告式地控制回滾語義的詳細資訊,請參閱 @Transactional 設定。
建議向 Spring 框架的事務基礎設施表明事務工作需要回滾的方式是,在當前在事務上下文中執行的程式碼中丟擲 Exception。Spring 框架的事務基礎設施程式碼會捕獲任何未處理的 Exception,因為它會冒泡到呼叫堆疊中,並確定是否將事務標記為回滾。
在其預設配置中,Spring 框架的事務基礎設施程式碼僅在執行時未檢查異常的情況下將事務標記為回滾。也就是說,當丟擲的異常是 RuntimeException 的例項或子類時。(Error 例項也預設導致回滾)。
預設配置還支援 Vavr 的 Try 方法,當它返回“Failure”時觸發事務回滾。這允許您使用 Try 處理函式式錯誤,並在失敗時自動回滾事務。有關 Vavr 的 Try 的更多資訊,請參閱官方 Vavr 文件。以下是如何將 Vavr 的 Try 與事務方法一起使用的示例
-
Java
@Transactional
public Try<String> myTransactionalMethod() {
// If myDataAccessOperation throws an exception, it will be caught by the
// Try instance created with Try.of() and wrapped inside the Failure class
// which can be checked using the isFailure() method on the Try instance.
return Try.of(delegate::myDataAccessOperation);
}
從 Spring Framework 6.1 開始,還對 CompletableFuture(以及一般的 Future)返回值進行了特殊處理,如果此類控制代碼在從原始方法返回時異常完成,則會觸發回滾。這適用於 @Async 方法,其中實際方法實現可能需要符合 CompletableFuture 簽名(在執行時透過 @Async 處理自動適應代理呼叫的實際非同步控制代碼),優先在返回的控制代碼中公開而不是重新丟擲異常。
-
Java
@Transactional @Async
public CompletableFuture<String> myTransactionalMethod() {
try {
return CompletableFuture.completedFuture(delegate.myDataAccessOperation());
}
catch (DataAccessException ex) {
return CompletableFuture.failedFuture(ex);
}
}
在預設配置中,從事務方法丟擲的檢查異常不會導致回滾。您可以透過指定回滾規則來精確配置哪些 Exception 型別標記事務進行回滾,包括檢查異常。
|
回滾規則
回滾規則確定在丟擲給定異常時是否應回滾事務,並且這些規則基於異常型別或異常模式。 回滾規則可以在 XML 中透過 當使用異常型別定義回滾規則時——例如,透過 當使用異常模式定義回滾規則時,模式可以是異常型別的完全限定類名或完全限定類名的子字串(必須是
|
以下 XML 片段演示瞭如何透過 rollback-for 屬性提供異常模式來配置檢查的、特定於應用程式的 Exception 型別回滾
<tx:advice id="txAdvice" transaction-manager="txManager">
<tx:attributes>
<tx:method name="get*" read-only="true" rollback-for="NoProductInStockException"/>
<tx:method name="*"/>
</tx:attributes>
</tx:advice>
如果您不希望在丟擲異常時回滾事務,您還可以指定“不回滾”規則。以下示例告訴 Spring 框架的事務基礎設施即使在出現未處理的 InstrumentNotFoundException 時也要提交附帶的事務
<tx:advice id="txAdvice">
<tx:attributes>
<tx:method name="updateStock" no-rollback-for="InstrumentNotFoundException"/>
<tx:method name="*"/>
</tx:attributes>
</tx:advice>
當 Spring 框架的事務基礎設施捕獲到異常並查閱配置的回滾規則以確定是否將事務標記為回滾時,最強的匹配規則獲勝。因此,在以下配置中,除了 InstrumentNotFoundException 之外的任何異常都會導致附帶事務的回滾
<tx:advice id="txAdvice">
<tx:attributes>
<tx:method name="*" rollback-for="Throwable" no-rollback-for="InstrumentNotFoundException"/>
</tx:attributes>
</tx:advice>
您還可以以程式設計方式指示所需的滾動回。雖然簡單,但此過程具有侵入性,並使您的程式碼與 Spring 框架的事務基礎設施緊密耦合。以下示例顯示瞭如何以程式設計方式指示所需的滾動回
-
Java
-
Kotlin
public void resolvePosition() {
try {
// some business logic...
} catch (NoProductInStockException ex) {
// trigger rollback programmatically
TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
}
}
fun resolvePosition() {
try {
// some business logic...
} catch (ex: NoProductInStockException) {
// trigger rollback programmatically
TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
}
}
強烈建議您儘可能使用宣告式回滾方法。如果您絕對需要,可以使用程式設計回滾,但它的使用與實現基於 POJO 的純淨架構相悖。