1. 程式人生 > >SpringBoot事務註解@Transactional

SpringBoot事務註解@Transactional

SpringBoot提供了非常方便的事務操作,通過註解就可以實現事務的回滾,非常方便快捷,下面我們就說一下如何進行事務操作。

1. 事務說明

在Spring中,事務有兩種實現方式,分別是程式設計式事務管理和宣告式事務管理兩種方式。
程式設計式事務管理: 程式設計式事務管理使用TransactionTemplate或者直接使用底層的PlatformTransactionManager。對於程式設計式事務管理,spring推薦使用TransactionTemplate。
宣告式事務管理: 建立在AOP之上的。其本質是對方法前後進行攔截,然後在目標方法開始之前建立或者加入一個事務,在執行完目標方法之後根據執行情況提交或者回滾事務。
宣告式事務管理不需要入侵程式碼,通過@Transactional就可以進行事務操作,更快捷而且簡單。推薦使用

2. 如何使用

在Mybatis中使用事務,非常簡單,只需要在函式增加註解@Transactional,無需任何配置。我們通過在controller層增加事務例子看下:


@Autowired
OrderServiceorderService;   //order操作的Service層

@ApiOperation(value = "增加OrderCustomer")
@RequestMapping(value = "", method = RequestMethod.POST)
@ResponseBody
@Transactional
public JsonBean<Order> insertOrder
(@RequestParam(value = "order") String order) { try { //建立訂單 Order order = orderService.insert(user.getId(),is_company,fk_want_company_id); return new JsonBean(SUCCESS, orderCustomer); } catch (ErrorCodeException e) { TransactionAspectSupport.currentTransactionStatus().setRollbackOnly(); return
new JsonBean(e.getErrorCode()); } }

@Transactional可以作用於介面、介面方法、類以及類方法上。當作用於類上時,該類的所有 public 方法將都具有該型別的事務屬性,同時,我們也可以在方法級別使用該標註來覆蓋類級別的定義。因此可以在Service層和Controller層使用,上述例子我們在Controller層實現,我們模擬了一個訂單提交的介面,其中JsonBean是統一返回錯誤碼基類,ErrorCodeException是自定義異常。

  1. 通過@Transactional,實現了事務操作。
  2. Spring的AOP即宣告式事務管理預設是針對unchecked exception回滾。也就是預設對RuntimeException()異常或是其子類進行事務回滾;checked異常,即Exception可try{}捕獲的不會回滾,因此對於我們自定義異常,通過rollbackFor進行設定,後續會單獨講
  3. 如果我們需要捕獲異常後,同時進行回滾,通過TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();進行手動回滾操作。
  4. 使用Object savePoint = TransactionAspectSupport.currentTransactionStatus().createSavepoint();
    設定回滾點,使用TransactionAspectSupport.currentTransactionStatus().rollbackToSavepoint(savePoint);回滾到savePoint。

3.常用配置

參 數 名 稱 功 能 描 述
readOnly 該屬性用於設定當前事務是否為只讀事務,設定為true表示只讀,false則表示可讀寫,預設值為false。例如:@Transactional(readOnly=true)
rollbackFor 該屬性用於設定需要進行回滾的異常類陣列,當方法中丟擲指定異常陣列中的異常時,則進行事務回滾。例如:指定單一異常類:@Transactional(rollbackFor=RuntimeException.class)指定多個異常類:@Transactional(rollbackFor={RuntimeException.class, Exception.class})
rollbackForClassName 該屬性用於設定需要進行回滾的異常類名稱陣列,當方法中丟擲指定異常名稱陣列中的異常時,則進行事務回滾。例如:指定單一異常類名稱@Transactional(rollbackForClassName=”RuntimeException”)指定多個異常類名稱:@Transactional(rollbackForClassName={“RuntimeException”,”Exception”})
noRollbackFor 該屬性用於設定不需要進行回滾的異常類陣列,當方法中丟擲指定異常陣列中的異常時,不進行事務回滾。例如:指定單一異常類:@Transactional(noRollbackFor=RuntimeException.class)指定多個異常類:@Transactional(noRollbackFor={RuntimeException.class, Exception.class})
noRollbackForClassName 該屬性用於設定不需要進行回滾的異常類名稱陣列,當方法中丟擲指定異常名稱陣列中的異常時,不進行事務回滾。例如:指定單一異常類名稱:@Transactional(noRollbackForClassName=”RuntimeException”)指定多個異常類名稱:@Transactional(noRollbackForClassName={“RuntimeException”,”Exception”})
propagation 該屬性用於設定事務的傳播行為。例如:@Transactional(propagation=Propagation.NOT_SUPPORTED,readOnly=true)
isolation 該屬性用於設定底層資料庫的事務隔離級別,事務隔離級別用於處理多事務併發的情況,通常使用資料庫的預設隔離級別即可,基本不需要進行設定
timeout 該屬性用於設定事務的超時秒數,預設值為-1表示永不超時

4. 事務屬性

事務隔離級別
隔離級別是指若干個併發的事務之間的隔離程度。TransactionDefinition 介面中定義了五個表示隔離級別的常量:

TransactionDefinition.ISOLATION_DEFAULT:這是預設值,表示使用底層資料庫的預設隔離級別。對大部分資料庫而言,通常這值就是TransactionDefinition.ISOLATION_READ_COMMITTED。
TransactionDefinition.ISOLATION_READ_UNCOMMITTED:該隔離級別表示一個事務可以讀取另一個事務修改但還沒有提交的資料。該級別不能防止髒讀,不可重複讀和幻讀,因此很少使用該隔離級別。比如PostgreSQL實際上並沒有此級別。
TransactionDefinition.ISOLATION_READ_COMMITTED:該隔離級別表示一個事務只能讀取另一個事務已經提交的資料。該級別可以防止髒讀,這也是大多數情況下的推薦值。
TransactionDefinition.ISOLATION_REPEATABLE_READ:該隔離級別表示一個事務在整個過程中可以多次重複執行某個查詢,並且每次返回的記錄都相同。該級別可以防止髒讀和不可重複讀。
TransactionDefinition.ISOLATION_SERIALIZABLE:所有的事務依次逐個執行,這樣事務之間就完全不可能產生干擾,也就是說,該級別可以防止髒讀、不可重複讀以及幻讀。但是這將嚴重影響程式的效能。通常情況下也不會用到該級別。

事務傳播行為
所謂事務的傳播行為是指,如果在開始當前事務之前,一個事務上下文已經存在,此時有若干選項可以指定一個事務性方法的執行行為。在TransactionDefinition定義中包括瞭如下幾個表示傳播行為的常量:

TransactionDefinition.PROPAGATION_REQUIRED:如果當前存在事務,則加入該事務;如果當前沒有事務,則建立一個新的事務。這是預設值。
TransactionDefinition.PROPAGATION_REQUIRES_NEW:建立一個新的事務,如果當前存在事務,則把當前事務掛起。
TransactionDefinition.PROPAGATION_SUPPORTS:如果當前存在事務,則加入該事務;如果當前沒有事務,則以非事務的方式繼續執行。
TransactionDefinition.PROPAGATION_NOT_SUPPORTED:以非事務方式執行,如果當前存在事務,則把當前事務掛起。
TransactionDefinition.PROPAGATION_NEVER:以非事務方式執行,如果當前存在事務,則丟擲異常。
TransactionDefinition.PROPAGATION_MANDATORY:如果當前存在事務,則加入該事務;如果當前沒有事務,則丟擲異常。
TransactionDefinition.PROPAGATION_NESTED:如果當前存在事務,則建立一個事務作為當前事務的巢狀事務來執行;如果當前沒有事務,則該取值等價於TransactionDefinition.PROPAGATION_REQUIRED。

事務超時
所謂事務超時,就是指一個事務所允許執行的最長時間,如果超過該時間限制但事務還沒有完成,則自動回滾事務。在 TransactionDefinition 中以 int 的值來表示超時時間,其單位是秒。
預設設定為底層事務系統的超時值,如果底層資料庫事務系統沒有設定超時值,那麼就是none,沒有超時限制。

事務只讀屬性
只讀事務用於客戶程式碼只讀但不修改資料的情形,只讀事務用於特定情景下的優化,比如使用Hibernate的時候。
預設為讀寫事務。