搜尋
首頁Javajava教程Spring事務的管理操作方法

Spring事務的管理操作方法

Jun 20, 2017 pm 04:20 PM
spring事務聲明問題

疑問,確實像往常一樣在service上添加了註解 @Transactional,為什麼查詢資料庫時還是發現有資料不一致的情況,想想肯定是事務沒起作用,出現異常的時候數據沒有回滾。於是就對相關程式碼進行了一番測試,結果發現一下踩進了兩個坑,確實是事務未回滾導致的資料不一致。以下總結經驗教訓:

Spring事務的管理操作方法

  • 編程式的交易管理

    • 實際應用中很少使用

    • 透過使用TransactionTemplate 手動管理交易

  • 聲明式的事務管理

    • 開發中推薦使用(程式碼侵入最少)

    • Spring的宣告式交易是透過AOP實現的

主要掌握宣告式的交易管理。

spring事務不回滾的兩個原因

總結一下導致事務不回滾的兩個原因,一是Service類別內部方法調用,二是try...catch異常。

1. Service類別內部方法呼叫

大概就是Service 中有一個方法A,會內部呼叫方法B, 方法A 沒有事務管理,方法B 採用了宣告式事務,透過在方法上聲明Transactional 的註解來做事務管理。範例程式碼如下:

@Servicepublic class RabbitServiceImpl implements RabbitService {

    @Autowiredprivate RabbitDao rabbitDao;
    @Autowiredprivate TortoiseDao tortoiseDao;

    @Overridepublic Rabbit methodA(String name){return methodB(name);
    }

    @Transactional(propagation = Propagation.REQUIRED)public boolean methodB(String name){
        rabbitDao.insertRabbit(name);
        tortoiseDao.insertTortoise(name);return true;
    }

}

單元測試程式碼如下:

public class RabbitServiceImplTest {

    @Autowiredprivate RabbitService rabbitService;// 事务未开启    @Testpublic void testA(){
        rabbitService.methodA("rabbit");
    }// 事务开启    @Testpublic void testB(){
        rabbitService.methodB("rabbit");
    }
}

從上一節可以看到,宣告式交易是通通過AOP動態代理實現的,這樣會產生一個代理類別來做事務管理,而目標類別(service)本身是不能感知代理類別的存在的。

對於加了@Transactional註解的方法來說,在呼叫代理類別的方法時,會先透過攔截器TransactionInterceptor開啟事務,然後在呼叫目標類別的方法,最後在呼叫結束後,TransactionInterceptor 會提交或回滾事務,大致流程如下圖:

Spring事務的管理操作方法

總結,在方法A 中呼叫方法B,實際上是透過「this」的引用,也就是直接調用了目標類的方法,而非透過Spring 上下文獲得的代理類,所以事務是不會開啟的。

2. try...catch異常

在一段業務邏輯中對資料庫異常進行了處理,使用了try...catch子句捕獲異常並throw了一個自定義異常,這種情況導致了事務未回滾,範例程式碼如下:

@Transactional(propagation = Propagation.REQUIRED)public boolean methodB(String name) throws BizException {try {
        rabbitDao.insertRabbit(name);
        tortoiseDao.insertTortoise(name);
    } catch (Exception e) {throw new BizException(ReturnCode.EXCEPTION.code, ReturnCode.EXCEPTION.msg);
    }return true;
}

BizException的定義如下:

public class BizException extends Exception {// 自定义异常}

上面程式碼中的聲明式事務在出現異常的時候,事務是不會回滾的。在程式碼中我雖然捕獲了異常,但是同時我也拋出了異常,為什麼事務未回滾呢?猜測是異常類型不對,於是開始查詢原因,翻看了Spring的官方文檔,找到了答案。下面是翻譯自Spring官網。

17.5.3 聲明式事務的回滾

上一節中介紹瞭如何設置開啟Spring事務,一般在你的應用的Service層代碼中設置,這一節將介紹在簡單流行的聲明式交易中如何控制交易回滾。

在Spring FrameWork 的交易框架中推薦的交易回滾方法是,在目前執行的交易上下文中拋出一個例外。如果異常未被處理,當拋出異常呼叫堆疊的時候,Spring FrameWork 的交易框架程式碼將捕獲任何未處理的異常,然後並決定是否將此交易標記為回滾。

  • 在預設設定中,Spring FrameWork 的交易框架程式碼只會將出現runtime, unchecked 例外的交易標記為回溯;也就是說交易中拋出的異常時RuntimeException或其子類,這樣事務才會回滾(預設情況下Error也會導致事務回滾)。在預設設定的情況下,所有的 checked 異常都不會造成交易回滾。

  註:Unchecked Exception包含Error與RuntimeException. RuntimeException的所有子類別也都屬於此類。另一類就是checked Exception。

  • 你可以精確的設定異常類型,指定此異常類別交易回滾,包括 checked 例外。下面的xml程式碼片段展示如何設定checked異常會造成交易回滾,應用自訂例外類型:

#
<advice>
  <attributes>
  <method></method>
  <method></method>
  </attributes>
</advice>

與其有同等作用的註解形式如下:

@Transactional(rollbackForClassName={"Exception"})
或者
@Transactional(rollbackFor={Exception.class})
  • 在你遇到异常不想回滚事务的时候,同样的你也可指定不回滚的规则,下面的一个例子告诉你,即使遇到未处理的 InstrumentNotFoundException 异常时,Spring FrameWork 的事务框架同样会提交事务,而不回滚。

<advice>
  <attributes>
  <method></method>
  <method></method>
  </attributes>
</advice>

  与其有同样作用的注解形式如下:   

@Transactional(noRollbackForClassName={"InstrumentNotFoundException"})
或者
@Transactional(noRollbackFor={InstrumentNotFoundException.class})
  • 还有更灵活的回滚规则配置方法,同时指定什么异常回滚,什么异常不回滚。当Spring FrameWork 的事务框架捕获到一个异常的时候,会去匹配配置的回滚规则来决定是否标记回滚事务,使用匹配度最强的规则结果。因此,下面的配置例子表达的意思是,除了异常 InstrumentNotFoundException 之外的任何异常都会导致事务回滚。

<advice>
  <attributes>
  <method></method>
  </attributes>
</advice>
  • 你也可以通过编程式的方式回滚一个事务,尽管方法非常简单,但是也有非常强的代码侵入性,使你的业务代码和Spring FrameWork 的事务框架代码紧密的绑定在一起,示例代码如下:

public void resolvePosition() {  try {      // some business logic...
  } catch (NoProductInStockException ex) {      // trigger rollback programmatically      TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
  }
}

  如果可能的话,强烈推荐您使用声明式事务方式回滚事务,对于编程式事务,如果你强烈需要它,也是可以使用的,but its usage flies in the face of achieving a clean POJO-based architecture.(没懂...)

看完官方文档这节内容找到了问题的答案,原来是因为我们自定义的异常不是 RuntimeException。我的解决办法是,在注解@Transactional中添加 rollbackFor={BizException.class}。可能你会问我为什么不将自定义异常修改为继承RuntimeException,因为我需要BizException是一个checked 异常。

以上是Spring事務的管理操作方法的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
為什麼Java是開發跨平台桌面應用程序的流行選擇?為什麼Java是開發跨平台桌面應用程序的流行選擇?Apr 25, 2025 am 12:23 AM

javaispopularforcross-platformdesktopapplicationsduetoits“ writeonce,runany where”哲學。 1)itusesbytiesebyTecodeThatrunsonAnyJvm-備用Platform.2)librarieslikeslikeslikeswingingandjavafxhelpcreatenative-lookingenative-lookinguisis.3)

討論可能需要在Java中編寫平台特定代碼的情況。討論可能需要在Java中編寫平台特定代碼的情況。Apr 25, 2025 am 12:22 AM

在Java中編寫平台特定代碼的原因包括訪問特定操作系統功能、與特定硬件交互和優化性能。 1)使用JNA或JNI訪問Windows註冊表;2)通過JNI與Linux特定硬件驅動程序交互;3)通過JNI使用Metal優化macOS上的遊戲性能。儘管如此,編寫平台特定代碼會影響代碼的可移植性、增加複雜性、可能帶來性能開銷和安全風險。

與平台獨立性相關的Java開發的未來趨勢是什麼?與平台獨立性相關的Java開發的未來趨勢是什麼?Apr 25, 2025 am 12:12 AM

Java將通過雲原生應用、多平台部署和跨語言互操作進一步提昇平台獨立性。 1)雲原生應用將使用GraalVM和Quarkus提升啟動速度。 2)Java將擴展到嵌入式設備、移動設備和量子計算機。 3)通過GraalVM,Java將與Python、JavaScript等語言無縫集成,增強跨語言互操作性。

Java的強鍵入如何有助於平台獨立性?Java的強鍵入如何有助於平台獨立性?Apr 25, 2025 am 12:11 AM

Java的強類型系統通過類型安全、統一的類型轉換和多態性確保了平台獨立性。 1)類型安全在編譯時進行類型檢查,避免運行時錯誤;2)統一的類型轉換規則在所有平台上一致;3)多態性和接口機制使代碼在不同平台上行為一致。

說明Java本機界面(JNI)如何損害平台獨立性。說明Java本機界面(JNI)如何損害平台獨立性。Apr 25, 2025 am 12:07 AM

JNI會破壞Java的平台獨立性。 1)JNI需要特定平台的本地庫,2)本地代碼需在目標平台編譯和鏈接,3)不同版本的操作系統或JVM可能需要不同的本地庫版本,4)本地代碼可能引入安全漏洞或導致程序崩潰。

是否有任何威脅或增強Java平台獨立性的新興技術?是否有任何威脅或增強Java平台獨立性的新興技術?Apr 24, 2025 am 12:11 AM

新興技術對Java的平台獨立性既有威脅也有增強。 1)雲計算和容器化技術如Docker增強了Java的平台獨立性,但需要優化以適應不同雲環境。 2)WebAssembly通過GraalVM編譯Java代碼,擴展了其平台獨立性,但需與其他語言競爭性能。

JVM的實現是什麼,它們都提供了相同的平台獨立性?JVM的實現是什麼,它們都提供了相同的平台獨立性?Apr 24, 2025 am 12:10 AM

不同JVM實現都能提供平台獨立性,但表現略有不同。 1.OracleHotSpot和OpenJDKJVM在平台獨立性上表現相似,但OpenJDK可能需額外配置。 2.IBMJ9JVM在特定操作系統上表現優化。 3.GraalVM支持多語言,需額外配置。 4.AzulZingJVM需特定平台調整。

平台獨立性如何降低發展成本和時間?平台獨立性如何降低發展成本和時間?Apr 24, 2025 am 12:08 AM

平台獨立性通過在多種操作系統上運行同一套代碼,降低開發成本和縮短開發時間。具體表現為:1.減少開發時間,只需維護一套代碼;2.降低維護成本,統一測試流程;3.快速迭代和團隊協作,簡化部署過程。

See all articles

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

Video Face Swap

Video Face Swap

使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱工具

SAP NetWeaver Server Adapter for Eclipse

SAP NetWeaver Server Adapter for Eclipse

將Eclipse與SAP NetWeaver應用伺服器整合。

DVWA

DVWA

Damn Vulnerable Web App (DVWA) 是一個PHP/MySQL的Web應用程序,非常容易受到攻擊。它的主要目標是成為安全專業人員在合法環境中測試自己的技能和工具的輔助工具,幫助Web開發人員更好地理解保護網路應用程式的過程,並幫助教師/學生在課堂環境中教授/學習Web應用程式安全性。 DVWA的目標是透過簡單直接的介面練習一些最常見的Web漏洞,難度各不相同。請注意,該軟體中

SublimeText3 Mac版

SublimeText3 Mac版

神級程式碼編輯軟體(SublimeText3)

記事本++7.3.1

記事本++7.3.1

好用且免費的程式碼編輯器

VSCode Windows 64位元 下載

VSCode Windows 64位元 下載

微軟推出的免費、功能強大的一款IDE編輯器