"If you're gonna play the game, boy, ya gotta learn to play it right"
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 />
注解驅動。
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)
參考鏈接:
http://blog.csdn.net/rickiyeat/article/details/62042685
http://makaidong.com/liwen19870618/1/8997_11363588.html
圖片來源:The Gambler (movie)
台詞來源:The Gambler by Kenny Rogers