回滾宣告式事務
前面一節概述瞭如何在應用中宣告式地為類(通常是服務層類)指定事務設定的基礎知識。本節描述瞭如何在 XML 配置中以簡單、宣告式的方式控制事務的回滾。有關使用 @Transactional
註解宣告式控制回滾語義的詳細資訊,請參閱 @Transactional
設定。
向 Spring Framework 的事務基礎設施指示事務工作需要回滾的推薦方式是在當前在事務上下文中執行的程式碼中丟擲一個 Exception
。Spring Framework 的事務基礎設施程式碼會捕獲呼叫棧中冒泡上來的任何未處理的 Exception
,並決定是否將事務標記為回滾。
在其預設配置中,Spring Framework 的事務基礎設施程式碼僅在發生執行時 unchecked 異常時才將事務標記為回滾。也就是說,當丟擲的異常是 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);
}
}
從事務方法中丟擲的 checked 異常在預設配置下不會導致回滾。您可以透過指定回滾規則來精確配置哪些 Exception
型別會標記事務回滾,包括 checked 異常。
回滾規則
回滾規則確定當丟擲給定異常時是否應回滾事務,這些規則基於異常型別或異常模式。 回滾規則可以在 XML 中透過 當回滾規則使用異常型別定義時,該型別將用於匹配丟擲異常的型別及其超型別,從而提供型別安全性並避免在使用模式時可能發生的任何意外匹配。例如,值 當回滾規則使用異常模式定義時,模式可以是異常型別(必須是
|
以下 XML 片段演示瞭如何透過 rollback-for
屬性提供異常模式,從而為 checked 的、應用特定的 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 Framework 的事務基礎設施,即使遇到未處理的 InstrumentNotFoundException
,也要提交伴隨的事務。
<tx:advice id="txAdvice">
<tx:attributes>
<tx:method name="updateStock" no-rollback-for="InstrumentNotFoundException"/>
<tx:method name="*"/>
</tx:attributes>
</tx:advice>
當 Spring Framework 的事務基礎設施捕獲到異常並查閱配置的回滾規則以確定是否將事務標記為回滾時,最強的匹配規則生效。因此,在以下配置的情況下,除了 InstrumentNotFoundException
之外的任何異常都會導致伴隨事務的回滾。
<tx:advice id="txAdvice">
<tx:attributes>
<tx:method name="*" rollback-for="Throwable" no-rollback-for="InstrumentNotFoundException"/>
</tx:attributes>
</tx:advice>
您也可以透過程式設計式方式指示需要回滾。儘管簡單,但這個過程相當侵入性,並且將您的程式碼與 Spring Framework 的事務基礎設施緊密耦合。以下示例展示瞭如何程式設計式指示需要回滾。
-
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 的架構相悖。