今天在看Spring事務的處理,注意到了傳播級別這個參數,一共是以下幾個值
REQUIRED(0),
SUPPORTS(1),
MANDATORY(2),
REQUIRES_NEW(3),
NOT_SUPPORTED(4),
NEVER(5),
NESTED(6);
其他幾種不用多說,詳細可以戳這里,主要是結合自己的分析,感覺網上說到REQUIRES_NEW
和NESTED
的區別時,描述大都不太準確,所以做下記錄
先看如下代碼
class A {
public void invoke() {
try {
new B().invoke();
catch (Exception e) {
new C().invoke();
}
// 此處可能還有其他業務代碼
...
};
}
class B {
public void invoke() {};
}
class C {
public void invoke() {};
}
不論使用REQUIRES_NEW
或是NESTED
,在調用B的invoke時如果發生異常,都能正確完成業務邏輯
-
REQUIRES_NEW
執行到B時,A事物被掛起,B會新開了一個事務進行執行,B發生異常后,B中的修改都會回滾,然后外部事物繼續執行 -
NESTED
執行到B時,會創建一個savePoint,如果B中執行失敗,會將數據回滾到這個savePoint
重點來了,如果B處正常執行,就會產生區別了
-
REQUIRES_NEW
如果B正常執行,則B中的數據在A提交之前已經完成提交,其他線程已經可見其修改,這就意味著可能有臟數據的產生;同時,如果接下來A的其他邏輯發生了異常,A回滾,但是B已經完成提交,不會回滾了。當然,如果A接下來的邏輯沒有相關要求,那就無所謂了 -
NESTED
如果B正常執行,此時B中的修改并不會立即提交,而是在A提交時一并提交,如果A下面的邏輯中發生異常,A回滾時,B中的修改也會回滾,就可以避免上述情況的發生