在spring boot事務管理中,實現自接口platformtransactionmanager。
1
2
3
4
5
6
7
|
public interface platformtransactionmanager { org.springframework.transaction.transactionstatus gettransaction(org.springframework.transaction.transactiondefinition transactiondefinition) throws org.springframework.transaction.transactionexception; void commit(org.springframework.transaction.transactionstatus transactionstatus) throws org.springframework.transaction.transactionexception; void rollback(org.springframework.transaction.transactionstatus transactionstatus) throws org.springframework.transaction.transactionexception; } |
當我們使用了spring-boot-starter-jdbc依賴的時候,框 架會自動默認注入datasourcetransactionmanager。所以我們不需要任何額外 配置就可以用@transactional注解進行事務的使用。
jdbc事務管理器
在service中,被 @transactional 注解的方法,將支持事務。如果注解在類上,則整個類的所有方法都默認支持事務。
多事務管理器情況
一:可以通過實現transactionmanagementconfigurer接口,里面方法返回值是默認的事務管理器。
二:可以在具體執行方法上設置value
如果spring容器中存在多個 platformtransactionmanager 實例,并且沒有實現接口transactionmanagementconfigurer 指定默認值,在我們在方法上使用注解 @transactional 的時候,就必須要用value指定,如果不指定,則會拋出異常。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
|
//@enabletransactionmanagement // 開啟注解事務管理,等同于xml配置文件中的 <tx:annotation-driven /> @springbootapplication public class profiledemoapplication implements transactionmanagementconfigurer { @resource (name= "txmanager2" ) private platformtransactionmanager txmanager2; // 手動創建事務管理器1 datasource框架會自動注入 //在spring容器中,我們手工注解@bean 將被優先加載,框架不會重新實例化其他的 platformtransactionmanager 實現類。 @bean (name = "txmanager1" ) public platformtransactionmanager txmanager(datasource datasource) { return new datasourcetransactionmanager(datasource); } // 創建事務管理器2 @bean (name = "txmanager2" ) public platformtransactionmanager txmanager2(entitymanagerfactory factory) { return new jpatransactionmanager(factory); } // 實現接口 transactionmanagementconfigurer 方法,其返回值代表在擁有多個事務管理器的情況下默認使用的事務管理器 @override public platformtransactionmanager annotationdriventransactionmanager() { return txmanager2; } public static void main(string[] args) { springapplication.run(profiledemoapplication. class , args); } } |
具體實現
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
@component public class devsendmessage implements sendmessage { // 使用value具體指定使用哪個事務管理器 @transactional (value= "txmanager1" ) @override public void send() { system.out.println( ">>>>>>>>dev send()<<<<<<<<" ); send2(); } @transactional public void send2() { system.out.println( ">>>>>>>>dev send2()<<<<<<<<" ); } } |
隔離級別
1
2
3
4
5
6
7
8
9
10
11
|
public enum isolation { default (transactiondefinition.isolation_default), read_uncommitted(transactiondefinition.isolation_read_uncommitted), read_committed(transactiondefinition.isolation_read_committed), repeatable_read(transactiondefinition.isolation_repeatable_read), serializable(transactiondefinition.isolation_serializable); private final int value; isolation( int value) { this .value = value; } public int value() { return this .value; } } |
- default :這是默認值,表示使用底層數據庫的默認隔離級別。對大部分數據庫而言,通常這值就是: read_committed 。
- read_uncommitted :該隔離級別表示一個事務可以讀取另一個事務修改但還沒有提交的數據。該級別不能防止臟讀和不可重復讀,因此很少使用該隔離級別。
- read_committed :該隔離級別表示一個事務只能讀取另一個事務已經提交的數據。該級別可以防止臟讀,這也是大多數情況下的推薦值。
- repeatable_read :該隔離級別表示一個事務在整個過程中可以多次重復執行某個查詢,并且每次返回的記錄都相同。即使在多次查詢之間有新增的數據滿足該查詢,這些新增的記錄也會被忽略。該級別可以防止臟讀和不可重復讀。
- serializable :所有的事務依次逐個執行,這樣事務之間就完全不可能產生干擾,也就是說,該級別可以防止臟讀、不可重復讀以及幻讀。但是這將嚴重影響程序的性能。通常情況下也不會用到該級別。
指定方法:通過使用 isolation 屬性設置,例如:
1
|
@transactional (isolation = isolation. default ) |
傳播行為
所謂事務的傳播行為是指,如果在開始當前事務之前,一個事務上下文已經存在,此時有若干選項可以指定一個事務性方法的執行行為。
我們可以看 org.springframework.transaction.annotation.propagation 枚舉類中定義了6個表示傳播行為的枚舉值:
1
2
3
4
5
6
7
8
9
10
11
12
|
public enum propagation { required(transactiondefinition.propagation_required), supports(transactiondefinition.propagation_supports), mandatory(transactiondefinition.propagation_mandatory), requires_new(transactiondefinition.propagation_requires_new), not_supported(transactiondefinition.propagation_not_supported), never(transactiondefinition.propagation_never), nested(transactiondefinition.propagation_nested); private final int value; propagation( int value) { this .value = value; } public int value() { return this .value; } } |
required :如果當前存在事務,則加入該事務;如果當前沒有事務,則創建一個新的事務。默認值。
supports :如果當前存在事務,則加入該事務;如果當前沒有事務,則以非事務的方式繼續運行。
mandatory :如果當前存在事務,則加入該事務;如果當前沒有事務,則拋出異常。(強制放入事務中)
requires_new :創建一個新的事務,如果當前存在事務,則把當前事務掛起。(打印日志常用,即使前面回滾,該事務也會執行,記錄報錯信息)
not_supported :以非事務方式運行,如果當前存在事務,則把當前事務掛起。
never :以非事務方式運行,如果當前存在事務,則拋出異常。
nested :如果當前存在事務,則創建一個事務作為當前事務的嵌套事務來運行;如果當前沒有事務,則該取值等價于 required 。
指定方法:通過使用 propagation 屬性設置,例如:
1
|
@transactional (propagation = propagation.required) |
事務不回滾情況
只在發生未被捕獲的 runtimeexception 時才回滾
catch拋出的異常,兩次插入都會成功
1
2
3
4
5
6
7
8
9
10
11
|
@override @transactional public void insertandinsert(staff staff) { staffdao.insert(staff); try { int i = 1 / 0 ; } catch (exception e){ e.printstacktrace(); } staffdao.insert(staff); } |
在service層方法的catch語句中增加:transactionaspectsupport.currenttransactionstatus().setrollbackonly();語句,手動回滾不會插入數據
1
2
3
4
5
6
7
8
9
10
11
|
@override @transactional public void insertandinsert(staff staff) throws exception { try { staffdao.insert(staff); int i= 1 / 0 ; staffdao.insert(staff); } catch (exception e){ transactionaspectsupport.currenttransactionstatus().setrollbackonly(); } } |
以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持服務器之家。
原文鏈接:http://www.jianshu.com/p/1ff821a0f070