天天看點

SpringBoot設定事務隔離等級

Spring Boot 使用事務非常簡單,首先使用注解 @EnableTransactionManagement 開啟事務支援後,然後在通路資料庫的Service方法上添加注解 @Transactional 便可。(在下文中會有圖例)

關于事務管理器,不管是JPA還是JDBC等都實作自接口 PlatformTransactionManager 如果你添加的是 spring-boot-starter-jdbc 依賴,架構會預設注入 DataSourceTransactionManager 執行個體。如果Spring容器中存在多個 PlatformTransactionManager 執行個體,并且沒有實作接口 TransactionManagementConfigurer 指定預設值,在我們在方法上使用注解 @Transactional 的時候,就必須要用value指定,如果不指定,則會抛出異常。對于系統需要提供預設事務管理的情況下,實作接口 TransactionManagementConfigurer 指定。對有的系統,為了避免不必要的問題,在業務中必須要明确指定 @Transactional 的 value 值的情況下。不建議實作接口 TransactionManagementConfigurer,這樣控制台會明确抛出異常,開發人員就不會忘記主動指定(這樣也更友善的控制不同業務上使用事務)。

一、配置步驟:

1、在啟動主類添加注解:​

​@EnableTransactionManagement​

​ 來啟用注解式事務管理,相當于之前在xml中配置的​

​<tx:annotation-driven />​

​注解驅動。

1

2

3

4

5

6

7

8

9

10

11

12

13

14

​package​

​ ​

​com.lgy.controller; ​

​import​

​org.springframework.boot.SpringApplication; ​

​import​

​org.springframework.boot.autoconfigure.SpringBootApplication; ​

​/** ​

​* Created by fengch on 2017/12/6. ​

​*/​

​ 

​@SpringBootApplication​

​  ​

​@EnableTransactionManagement​

​public​

​class​

​AppMain { ​

​public​

​static​

​void​

​main(String[] args) { ​

​SpringApplication.run(AppMain.​

​​

​class​

​, args); ​

​} ​

​} ​

  

2、在需要事務的類或者方法(service)上面添加​

​@Transactional()​

​ 注解,裡面可以配置需要的粒度,如開頭說到的,如果沒有設定預設的事務等級,需要在此添加isolation和propagation屬性,還有幾個其他的屬性可以設定,在此隻介紹這兩個比較重要的屬性。

​@Transactional​

​(isolation = Isolation.DEFAULT,propagation = Propagation.REQUIRED)​

​public​

​class​

​DefaultFooService ​

​implements​

​FooService {​

​public​

​void​

​getFoo(Foo foo) {​

​// do something​

​  }​

​//方法上注解屬性會覆寫類注解上的相同屬性​

​@Transactional​

​(readOnly = ​

​false​

​, propagation = Propagation.REQUIRES_NEW)​

​public​

​void​

​updateFoo(Foo foo) {​

​// do something​

​  }​

​}​

二、屬性配置:

1、Isolation :隔離級别

隔離級别是指若幹個并發的事務之間的隔離程度,與我們開發時候主要相關的場景包括:髒讀取、重複讀、幻讀。

我們可以看 ​

​org.springframework.transaction.annotation.Isolation​

​ 枚舉類中定義了五個表示隔離級别的值:

public enum Isolation {  
    DEFAULT(-1),
    READ_UNCOMMITTED(1),
    READ_COMMITTED(2),
    REPEATABLE_READ(4),
    SERIALIZABLE(8);
}      

​DEFAULT​

​ :這是預設值,表示使用底層資料庫的預設隔離級别。對大部分資料庫而言,通常這值就是: ​

​READ_COMMITTED​

​ 。 

​READ_UNCOMMITTED​

​ :該隔離級别表示一個事務可以讀取另一個事務修改但還沒有送出的資料。該級别不能防止髒讀和不可重複讀,是以很少使用該隔離級别。 

​READ_COMMITTED​

​ :該隔離級别表示一個事務隻能讀取另一個事務已經送出的資料。該級别可以防止髒讀,這也是大多數情況下的推薦值。 

​REPEATABLE_READ​

​ :該隔離級别表示一個事務在整個過程中可以多次重複執行某個查詢,并且每次傳回的記錄都相同。即使在多次查詢之間有新增的資料滿足該查詢,這些新增的記錄也會被忽略。該級别可以防止髒讀和不可重複讀。 

​SERIALIZABLE​

​ :所有的事務依次逐個執行,這樣事務之間就完全不可能産生幹擾,也就是說,該級别可以防止髒讀、不可重複讀以及幻讀。但是這将嚴重影響程式的性能。通常情況下也不會用到該級别。 

指定方法:通過使用 ​

​isolation​

​ 屬性設定,例如:​

​@Transactional(isolation = Isolation.DEFAULT)/​

2、Propagation:傳播行為

所謂事務的傳播行為是指,如果在開始目前事務之前,一個事務上下文已經存在,此時有若幹選項可以指定一個事務性方法的執行行為。

​org.springframework.transaction.annotation.Propagation​

​ 枚舉類中定義了6個表示傳播行為的枚舉值:

public enum Propagation {  
    REQUIRED(0),
    SUPPORTS(1),
    MANDATORY(2),
    REQUIRES_NEW(3),
    NOT_SUPPORTED(4),
    NEVER(5),
    NESTED(6);
}      

​REQUIRED​

​ :如果目前存在事務,則加入該事務;如果目前沒有事務,則建立一個新的事務。 

​SUPPORTS​

​ :如果目前存在事務,則加入該事務;如果目前沒有事務,則以非事務的方式繼續運作。 

​MANDATORY​

​ :如果目前存在事務,則加入該事務;如果目前沒有事務,則抛出異常。 

​REQUIRES_NEW​

​ :建立一個新的事務,如果目前存在事務,則把目前事務挂起。 

​NOT_SUPPORTED​

​ :以非事務方式運作,如果目前存在事務,則把目前事務挂起。 

​NEVER​

​ :以非事務方式運作,如果目前存在事務,則抛出異常。 

​NESTED​

​ :如果目前存在事務,則建立一個事務作為目前事務的嵌套事務來運作;如果目前沒有事務,則該取值等價于 ​

​REQUIRED​

​propagation​

​@Transactional(propagation = Propagation.REQUIRED)​

梅花香自古寒來