Spring詳細講解7種事務傳播方式
Spring事務傳播行為體現(xiàn)在某個service方法調用另一個service方法,事務該如何進行下去。
Spring支持7中事務傳播方式,在Propagation類中可以看到,如下:
REQUIRED(0),
SUPPORTS(1),
MANDATORY(2),
REQUIRES_NEW(3),
NOT_SUPPORTED(4),
NEVER(5),
NESTED(6);
使用方式就是在service方法上加入Transational注解,例如:
@Transactional(propagation = Propagation.NOT_SUPPORTED)
下面逐個介紹下這7中事務傳播方式:
1. REQUIRED:
Spring的默認事務傳播方式。從字面意思看,它表示此枚舉修飾的service方法必須運行在一個事務中,如果當前存在一個事務(比如其他有事務的service方法調用此方法),則運行在當前事務中,否則開啟一個新的事務。
示例代碼如下:
注意:這里methodA調用methodB必須要用Spring的代理方式,即用testService.methodB()方式調用,如果只是method()方式調用則相當于this.methodB()在本對象中調用,事務不起作用的,一定要是Spring的AOP代理。@Lazy注解是為了防止啟動的時候出現(xiàn)循環(huán)依賴報錯,采用懶加載方式注入Bean。
下面示例中,methodA調用methodB的時候,會先開啟一個事務,methodB中會使用methodA這個事務,和methodA一起提交或回滾。
@Service
public class TestServiceImpl implements TestService {
@Resource @Lazy
private TestService testService;
@Transactional
@Override
public void methodA() {
testService.methodB();
System.out.println("CRUD operation in methodA...");
}
@Transactional
@Override
public void methodB() {
System.out.println("CRUD operation in methodB...");
}
}2. SUPPORTS:
從字面意思看,它是支持的意思,也就是有事務我也支持,沒有也行。
即:調用此方法時如果有一個事務,那么就在當前事務中執(zhí)行,和當前事務一起提交或回滾。如果當前沒有事務,那么就不開啟事務,在無事務環(huán)境中執(zhí)行。
下面示例代碼中,methodB是SUPPORTS事務傳播方式,methodB有沒有事務取決于調用它的methodA??梢钥吹酱藭rmethodA是有一個事務的,所以methodB會在methodA這個事務中一起提交或回滾。
@Service
public class TestServiceImpl implements TestService {
@Resource @Lazy
private TestService testService;
@Transactional
@Override
public void methodA() {
testService.methodB();
System.out.println("CRUD operation in methodA...");
}
@Transactional(propagation = Propagation.SUPPORTS)
@Override
public void methodB() {
System.out.println("CRUD operation in methodB...");
}
}3. MANDATORY:
字面意思:強制。
沒錯,就是一定要在事務中執(zhí)行,否則就會拋異常。
如下面的代碼,如果直接調用methodB,由于當前沒有事務,會拋出一個IllegalTransactionStateException異常。如果是在methodA中調用methodB,由于methodA開啟了一個事務,所以methodB會在methodA的事務中執(zhí)行,不會報錯。
@Service
public class TestServiceImpl implements TestService {
@Resource @Lazy
private TestService testService;
@Transactional
@Override
public void methodA() {
testService.methodB();
System.out.println("CRUD operation in methodA...");
}
@Transactional(propagation = Propagation.MANDATORY)
@Override
public void methodB() {
System.out.println("CRUD operation in methodB...");
}
}4. REQUIRES_NEW:
字面意思:開啟一個新的事務。
這個事務傳播方式會掛起當前事務,開啟一個新的事務,方法會在新的事務中執(zhí)行并提交,提交完之后,掛起的事務繼續(xù)往下走。
如下代碼,methodA調用methodB的時候,當前事務會被掛起,然后在methodB中會開啟一個新的事務,methodB執(zhí)行完并且事務提交后,methodA的事務繼續(xù)執(zhí)行。methodB回滾不影響methodA,methodA回滾也不影響methodB。
@Transactional
@Override
public void methodA() {
testService.methodB();
System.out.println("CRUD operation in methodA...");
}
@Transactional(propagation = Propagation.REQUIRES_NEW)
@Override
public void methodB() {
System.out.println("CRUD operation in methodB...");
}5. NOT_SUPPORTED:
字面意思:不支持事務。
用該枚舉修飾的方法一定會運行在非事務環(huán)境中,即使調用此方法時有一個事務,也會將該事務掛起。我們通常將這種方式應用于強制要求非事務的方法中,例如我們現(xiàn)在要將批量數(shù)據(jù)去集成第三方接口然后更新狀態(tài)到DB,不能說某一個數(shù)據(jù)出錯就導致所有數(shù)據(jù)狀態(tài)都回滾,那樣的話,已經(jīng)成功集成過第三方接口的數(shù)據(jù)就又得重新去集成了,會造成重復調用,導致第三方系統(tǒng)中的數(shù)據(jù)混亂。
如下代碼,methodA有一個事務,當它調用methodB時,事務會被掛起,然后methodB中的CRUD操作不會在事務中執(zhí)行,會立即提交到數(shù)據(jù)庫。methodB執(zhí)行完之后,methodA的事務繼續(xù)進行,methodA的回滾不影響methodB。
@Transactional
@Override
public void methodA() {
testService.methodB();
System.out.println("CRUD operation in methodA...");
}
@Transactional(propagation = Propagation.NOT_SUPPORTED)
@Override
public void methodB() {
System.out.println("CRUD operation in methodB...");
}6. NEVER:
字面意思:永遠也不在事務中運行。
該枚舉修飾的方法一旦在事務環(huán)境中就會拋異常。
7. NESTED:
字面意思:嵌套事務。
這種傳播方式稍微有點復雜,目前各種廠商對它的支持可能存在差異,需要看具體的事務管理實現(xiàn)方式。
用此枚舉修飾的方法,當外部有事務的時候,會在里面嵌套一個事務,里面的事務回滾不會影響外部事務,但外部事務出錯回滾會將里面的也一起回滾。
如下methodB會在methodA的事務里面再嵌套一個事務,當methodA事務提交,methodB也會跟著一起提交,當methodA出錯回滾,會把methodB也一起回滾。當methodB出錯回滾,不會影響methodA的事務,事務會回退到調用methodB前的節(jié)點,然后繼續(xù)處理后續(xù)的步驟。
@Transactional
@Override
public void methodA() {
System.out.println("CRUD operation in methodA before...");
//保存當前狀態(tài),開啟嵌套事務
try {
testService.methodB();
} catch (Exception e) {
e.printStackTrace();
}
//methodB回滾后不影響methodA事務繼續(xù)進行
System.out.println("CRUD operation in methodA...");
}
@Transactional(propagation = Propagation.NESTED)
@Override
public void methodB() {
System.out.println("CRUD operation in methodB...");
throw new RuntimeException("methodB rollback");
}到此這篇關于Spring詳細講解7種事務傳播方式的文章就介紹到這了,更多相關Spring事務傳播內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
springboot打包無法讀取yml、properties等配置文件的解決
這篇文章主要介紹了springboot打包無法讀取yml、properties等配置文件的解決方案,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2025-04-04
SpringMVC實現(xiàn)controller中獲取session的實例代碼
本篇文章主要介紹了SpringMVC實現(xiàn)controller中獲取session的實例代碼,具有一定的參考價值,有興趣的可以了解一下。2017-02-02
SpringCloud-Hystrix-Dashboard客戶端服務監(jiān)控的實現(xiàn)方法
這篇文章主要介紹了SpringCloud-Hystrix-Dashboard客戶端服務監(jiān)控的實現(xiàn)方法,本文通過實例代碼給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下2021-03-03
java中instanceof和getClass()的區(qū)別分析
本篇文章介紹了,在java中instanceof和getClass()的區(qū)別分析。需要的朋友參考下2013-04-04

