Spring中事務的傳播行為

  • 2019 年 10 月 4 日
  • 筆記

當我們在spring中調用Service中一個方法時,如果我們默認配置了對Service的事務管理,那麼此時的Service將運行在一個由spring管理的事務環境中。由於在我們日常的開發時,通常會在一個Service接口中調用其它Service中的接口以此來完成一個完整的事務操作,這時就會發生服務接口嵌套調用的情況,spring通過事務傳播行為控制當前事務如何傳播到被嵌套調用的目標服務接口方法中的。下面我們想想了解一下在spring中都有哪些不同的事務傳播行為,以前它們的區別。

spring在TransactionDefinition接口中定義了7種類型的事務傳播行為,它們具體的區別如下:

事務傳播行為說明

  • PROPAGATION_REQUIRED:如果當前沒有事務,那就新建一個新的事務,如果已經存在一個事務,那就加入到這個事務中。
  • PROPAGATION_SUPPORTS:支持當前事務,如果當前沒有事務,就以非事務方法執行。
  • PROPAGATION_MANDATORY:使用當前事務,如果當前沒有事務,則就拋出異常。
  • PROPAGATION_REQUIRES_NEW:新建事務,如果當前存在事務,則把當前事務掛起。
  • PROPAGATION_NOT_SUPPORTED:以非事務方式執行操作,如果當前存在事務,則把當前事務掛起。
  • PROPAGATION_NEVER:以非事務方式執行,如果當前存在事務,則拋出異常
  • PROPAGATION_NESTED:如果當前存在事務,則在嵌套事務內執行,如果當前沒有事務,則執行與PROPAGATION_REQUIRED類似的操作。

備註:當使有PROPAGATION_NESTED時,底層的數據源必須基於JDBC3.0,並且實現者需要支持保存點事務機制。

我們在實際開發時,基本不會通過編碼的方式來進行事務管理,因為這樣很不方便管理,在實際的開發中我們一般會採用xml的方法或者註解的方法來進行事務管理。雖然我們不會直接採用編碼的方法進行事務管理,但在spring中還是提供了對該方法的支持。我們可以直接使用spring為我們提供的TransactionTemplate模板類來執行我們用編碼的方式對事務進行管理。下面我們簡單了解一下TransactionTemplate模板類的主要方法。

下面我們通過一個簡單的測試用例來看一下到底怎麼用ransactionTemplate模板類通過編碼的方法進行事務管理。

由於spring事務管理器TransactionSynchronizationManager進行工作,所以如果在回調接口方法中需要顯示的訪問數據庫連接,必須通過資源獲取工具類得到線程綁定的數據連接,因為這是spring事務管理的底層協議。如果DAO接口是基於spring提供的模板類創建的,由於模板類已經在內部使用了資源獲取工具類獲取數據庫連接,所以用戶就不必關心底層數據連接的獲取問題了。

上面我們提到過,在我們日常開發時,不是會採用用編碼的方式管理事務的,我們基本上會採用聲明式事務管理功能,因為這種方式可以讓事務管理代碼完全從業務代碼中解耦。在spring中聲明式事務管理是通過spring AOP的功能實現的。具體的流程是通過事務的聲明信息,spring負責將事務管理增強邏輯動態織入到業務方法的相應連接點中。下面我們通過xml代碼的方法來管理事務。

UserDao接口中有兩個方法,我們可以對對save方法添加寫的事務能力,而對getUserInfo方法添加讀事務能力。

我們可以看到,採用xml管理事務和直接用編碼的方法有很大的不同的,在接口的實現類中只有相關的業務代碼,並不會有任何相關事務的代碼,而用直接編碼的方法則必須手動的將管理事務的代碼編寫在接口的實現類中。在spring中可以用兩種方式來通過xml管理事務,一種方式是TransactionProxyFactoryBean的方式來進行事務管理,還有一種方式是通過tx的方式來管理事務,因為TransactionProxyFactoryBean的方式spring官網中已經不推薦使用了,所以,我們下面的測試用例將採用用tx的方式來管理事務。