@Transactional中可以設(shè)置以下7種事務(wù)傳播行為
- REQUIRED:支持當(dāng)前事務(wù)顶别,如果當(dāng)前沒(méi)有事務(wù)纺涤,就新建一個(gè)事務(wù)数焊。這是最常見(jiàn)的選擇疯搅。
- SUPPORTS:支持當(dāng)前事務(wù),如果當(dāng)前沒(méi)有事務(wù)健爬,就以非事務(wù)方式執(zhí)行控乾。
- MANDATORY:支持當(dāng)前事務(wù),如果當(dāng)前沒(méi)有事務(wù)浑劳,就拋出異常阱持。
- REQUIRES_NEW:新建事務(wù),如果當(dāng)前存在事務(wù)魔熏,把當(dāng)前事務(wù)掛起衷咽。
- NOT_SUPPORTED:以非事務(wù)方式執(zhí)行操作,如果當(dāng)前存在事務(wù)蒜绽,就把當(dāng)前事務(wù)掛起镶骗。
- NEVER:以非事務(wù)方式執(zhí)行,如果當(dāng)前存在事務(wù)躲雅,則拋出異常鼎姊。
- NESTED:支持當(dāng)前事務(wù),如果當(dāng)前事務(wù)存在相赁,則執(zhí)行一個(gè)嵌套事務(wù)相寇,如果當(dāng)前沒(méi)有事務(wù),就新建一個(gè)事務(wù)钮科。
通常我們只會(huì)用到@Transactional(propagation = Propagation.REQUIRED)在特殊需求的時(shí)候需要在一個(gè)方法內(nèi)部提前提交一部分事務(wù)或者是讓內(nèi)部的一段代碼處于單獨(dú)的一個(gè)事務(wù)管理的時(shí)候需要用到REQUIRES_NEW
例如下面示例中的methodA需要單獨(dú)開(kāi)啟事務(wù)唤衫,不受調(diào)用方法事務(wù)的回滾而回滾:
@transaction
public void testMethod(){
dosomethingBefore...
methodA();
dosomgthingAfter...
}
@Transactional(propagation = Propagation.REQUIRES_NEW)
public void methodA(){
updateSomething();
}
假設(shè)我們?cè)贑ontroller直接調(diào)用testMethod() Spring會(huì)幫我們開(kāi)啟一個(gè)事務(wù)
運(yùn)行到methodA()這行的時(shí)候會(huì)掛起當(dāng)前事務(wù),然后重新創(chuàng)建一個(gè)事務(wù)绵脯,在methodA()中沒(méi)有發(fā)生異常的情況下佳励,運(yùn)行完methodA方法直接提交methodA的事務(wù);后續(xù)再執(zhí)行dosomgthingAfter蛆挫。
總共會(huì)有4種情況:
- dosomethingBefore發(fā)生異常赃承,這時(shí)methodA()未運(yùn)行也就沒(méi)有事務(wù),直接回滾testMethod()的事務(wù)悴侵。
- updateSomething發(fā)生異常瞧剖,回滾methodA()的事務(wù),此時(shí)如果testMethod()對(duì)這個(gè)異常進(jìn)行了try catch捕獲可免,testMethod的事務(wù)照常提交筒繁。
- updateSomething發(fā)生異常,回滾methodA()的事務(wù)巴元,此時(shí)如果testMethod()沒(méi)有對(duì)這個(gè)異常進(jìn)行try catch捕獲,那么methodA和testMethod的事務(wù)都會(huì)回滾驮宴。
- 前面全部正常 dosomgthingAfter 發(fā)生異常逮刨,這時(shí)methodA()事務(wù)已經(jīng)提交 testMethod()所做的修改會(huì)回滾。