天天看點

Spring事務的傳播級别

一、簡單說明

傳播屬性 描述
PROPAGATION_REQUIRED 如果目前沒有事務,就建立一個事務,如果目前存在事務,就加入該事務。
PROPAGATION_REQUIRED_NEW 目前的方法必須啟動新事務,并在它自己的事務内運作,不管是否存着事務,都開啟新事務。
PROPAGATION_SUPPORTS 如果目前存在事務,就加入該事務,如果目前不存在事務,就以非事務的方式執行。
PROPAGATION_NOT_SUPPORTED 目前的方法不應該運作在事務中,如果有運作的事務,将它挂起
PROPAGATION_MANDATORY 如果目前存在事務,就加入目前事務,如果目前不存在事務,就抛出異常
PROPAGATION_NEVER 目前的方法不應該運作在事務中,如果目前存在事務,就抛出異常
PROPAGATION_NESTED 如果有事務在運作,目前的方法就應該在這個事務的嵌套事務内運作,否則,就啟動一個新的事務,并在它自己的事務内運作。

二、具體案例描述

1.PROPAGATION_REQUIRED

@Transactional(propagation=PROPAGATION_REQUIRED)
pubilc void methodA(){
        doPreSomething;
        methodB();
        doSufSomething;
}

@Transactional(propagation=PROPAGATION_REQUIRED)
pubilc void methodB(){
        doSomething;
} 
           

在兩個方法的事務傳播級别都是PROPAGATION_REQURIED的時候。

如果調用方法A,會開啟一個事務,在方法A内部調用方法B,由于方法A已經存在開啟尚未送出的事務,方法B不會就不會再開啟一個新的事務,方法B會直接加入方法A的事務中執行,這樣如果在執行方法B的時候出了異常導緻事務復原,則B的方法和A的方法都會復原。如果A的doPreSomething()和方法B都執行成功了,但是在執行doSufSomething()方法的時候抛出了異常導緻事務復原,則doSufSomething()、methodB()和doPreSomething()都會復原。

如果不通過方法A而單獨調用方法B,則會開啟一個事務。

PROPAGATION_REQURIED所有方法公用一個事務,要麼一起成功送出,要麼一起失敗復原。

如果嵌套執行的方法要求一起執行成功或者一起復原,則選擇該事物傳播級别。

執行邏輯:

開啟事務

執行方法A的doPreSomething

執行方法B

執行方法A的doSufSomething

送出或復原事務

2.PROPAGATION_REQUIRED_NEW

@Transactional(propagation=PROPAGATION_REQUIRED)
pubilc void methodA(){
        doPreSomething;
        methodB();
        dosufSomething;
}

@Transactional(propagation=PROPAGATION_REQUIRED_NEW)
pubilc void methodB(){
       doSomething;
} 
           

在事務的隔離級别是PROPAGATION_REQUIRED_NEW的時候。

如果調用方法A,會開啟一個事務,在方法内部調用方法B,方法B會自己再開啟一個事務,然後方法B在自己的事務内部執行,如果方法B執行失敗抛出異常,那麼事務B會進行復原,事務A不會受到影響可以繼續執行,如果在方法B執行成功,方法B的事務會單獨進行送出;B送出事務之後接着執行A的doSufSomething()方法,如果執行成功送出A的事務,如果抛出異常,則隻復原A的事務,對B的事務不會進行影響,也就說B的事務不會進行復原。

如果不通過方法A而單獨調用方法B,則會開啟一個事務。

PROPAGATION_REQURIED_NEW所有方法使用各自的事務,各自送出或者復原各自的事務,互相之間不會造成影響。

如果嵌套執行的方法要求各自事務獨立,不能進行互相影響,則選擇本事務傳播級别。

執行邏輯

開啟事務

執行方法A的doPreSomething

開啟另一個事務2

執行方法B

送出或者復原事務2

執行方法A的doSufSomething

送出或復原事務

3.PROPAGATION_SUPPORTS

@Transactional(propagation=PROPAGATION_REQUIRED)
pubilc void methodA(){
        doPreSomething;
        methodB();
        doSufSomething;
}

@Transactional(propagation=PROPAGATION_SUPPORTS)
pubilc void methodB(){
       doSomething;
} 
           

在事務的隔離級别是PROPAGATION_SUPPORTS的時候。

如果調用方法A,會開啟一個事務,在方法A内部調用方法B,由于方法A已經存在開啟尚未送出的事務,方法B會直接加入方法A的事務中執行,這樣如果在執行方法B的時候出了異常導緻事務復原,則B的方法和A的方法都會復原。如果A的doPreSomething()和方法B都執行成功了,但是在執行doSufSomething()方法的時候抛出了異常導緻事務復原,則doSufSomething()、methodB()和doPreSomething()都會復原。

如果不通過方法A而單獨調用方法B,則方法B不會開啟事務,直接會以非事務的方式執行。

PROPAGATION_SUPPORTS如果存着事務就加入和PROPAGATION_REQUIRED傳播級别一緻,如果目前不存在事務,則不會建立新的事務,以非事務的方式執行。

如果嵌套執行的方法要求一起執行成功或者一起復原,單獨執行時候以非事務方式執行,則選擇該事物傳播級别。

執行邏輯:

開啟事務

執行方法A的doPreSomething

執行方法B

執行方法A的doSufSomething

送出或復原事務

4.PROPAGATION_NOT_SUPPORTED

@Transactional(propagation=PROPAGATION_REQUIRED)
pubilc void methodA(){
        doPreSomething;
        methodB();
        doSufSomething;
}

@Transactional(propagation=PROPAGATION_NOT_SUPPORTED)
pubilc void methodB(){
        doSomething;
} 
           

在事務的隔離級别是PROPAGATION_NOT_SUPPORTED的時候。

如果調用方法A,會開啟一個事務,在方法A内部調用方法B,由于方法A已經存在開啟尚未送出的事務,方法B不允許在事務内部執行,這時候事務就會挂起,在非事務的狀态中執行方法B,不管方法B是執行成功還是執行失敗,都不會對目前事務造成影響。如果A的doPreSomething()和方法B都執行成功了,但是在執行doSufSomething()方法的時候抛出了異常導緻事務復原,則doSufSomething()和doPreSomething()會復原,而方法B不會受到任何影響,因為它是在非事務中執行的。

如果不通過方法A而單獨調用方法B,則方法B不會開啟事務,直接會以非事務的方式執行。

PROPAGATION_NOT_SUPPORTED如果存着事務就挂起目前事務,以非事務的方式運作自己,如果目前不存在事務,則不會建立新的事務,以非事務的方式執行。

如果嵌套執行的方法要求内部嵌套方法不會對外部方法事務造成影響并且内部方法不需要事務,單獨執行時候以非事務方式執行,則選擇該事物傳播級别。

執行邏輯:

開啟事務

執行方法A的doPreSomething

挂起事務

執行方法B

重新啟用挂起的事務

執行方法A的doSufSomething

送出或復原事務

5.PROPAGATION_MANDATORY

@Transactional(propagation=PROPAGATION_REQUIRED)
pubilc void methodA(){
        doPreSomething;
        methodB();
        doSufSomething;
}

@Transactional(propagation=PROPAGATION_MANDATORY)
pubilc void methodB(){
       doSomething;
} 
           

在事務的隔離級别是PROPAGATION_MANDATORY的時候。

如果調用方法A,會開啟一個事務,在方法A内部調用方法B,由于方法A已經存在開啟尚未送出的事務,方法B會直接加入方法A的事務中執行,這樣如果在執行方法B的時候出了異常導緻事務復原,則B的方法和A的方法都會復原。如果A的doPreSomething()和方法B都執行成功了,但是在執行doSufSomething()方法的時候抛出了異常導緻事務復原,則doSufSomething()、methodB()和doPreSomething()都會復原。

如果不通過方法A而單獨調用方法B,則方法B會直接報錯,因為方法B的事務傳播級别是PROPAGATION_MANDATORY,而其不允許在沒有事務的環境下執行。

PROPAGATION_SUPPORTS如果存着事務就加入和PROPAGATION_REQUIRED傳播級别一緻,如果目前不存在事務,會直接進行報錯,不允許以非事務的方式執行。

如果嵌套執行的方法要求一起執行成功或者一起復原,單獨執行時候不允許以非事務方式執行,則選擇該事物傳播級别。

執行邏輯:

開啟事務

執行方法A的doPreSomething

執行方法B

執行方法A的doSufSomething

送出或復原事務

6.PROPAGATION_NEVER

@Transactional(propagation=PROPAGATION_REQUIRED)
pubilc void methodA(){
        doPreSomething;
        methodB();
        doSufSomething;
}

@Transactional(propagation=PROPAGATION_NEVER)
pubilc void methodB(){
        doSomething;
} 
           

在事務的隔離級别是PROPAGATION_NERVR的時候。

如果調用方法A,會開啟一個事務,在方法A内部調用方法B,由于方法A已經存在開啟尚未送出的事務,方法B的傳播級别為PROPAGATION_NEVER,其不允許在事務内部執行,是以這時候就會直接報錯。

如果不通過方法A而單獨調用方法B,則方法B會直接在沒有事務的環境中執行。

PROPAGATION_NERVER如果存着事務就直接報錯,如果目前不存在事務,會以非事務的方式執行。

如果嵌套執行的方法要求内部方法不允許在事務中執行,單獨執行時候必須以非事務方式執行,則選擇該事物傳播級别。

執行邏輯:

開啟事務

執行方法A的doPreSomething

執行方法B,直接報錯

復原事務

7.PROPAGATION_NESTED

@Transactional(propagation=PROPAGATION_REQUIRED)
pubilc void methodA(){
        doPreSomething;
        methodB();
        doSufSomething;
}

@Transactional(propagation=PROPAGATION_NESTED)
pubilc void methodB(){
        doSomething;
} 
           

在事務的隔離級别是PROPAGATION_NESTED的時候。

如果調用方法A,會開啟一個事務,在方法A内部調用方法B,由于方法A已經存在開啟尚未送出的事務,方法B的傳播級别為PROPAGATION_NESTED,會加入這個事務當中,但是在執行到方法B之前會建立一個事務的復原點(savepoint),然後執行方法B,如果方法B執行失敗了,事務會進行復原,但是這時指揮復原到復原點,也就是之後復原B的操作,外部方法的操作不會復原;如果B執行成功了,接着執行A的doSufSomething()方法,如果執行出錯,則會復原整個事務,也就是doSufSomething()、methodB()和doPreSomething()的執行都會進行復原。

如果直接調用方法B,則會開啟一個事務,和PROPAGATION_REQUIRED傳播級别一緻。

如果嵌套執行的方法要求内部方法出錯隻復原自己,外部方法執行失敗復原所有,單獨執行時候自動開啟一個執行,則選擇該事物傳播級别。

執行邏輯:

開啟事務

執行方法A的doPreSomething

建立復原點savepoint

執行方法B,失敗隻復原到savepoint

執行方法A的doSufSomething

送出或復原事務

三、總結

1、PROPAGATION_REQUIRED

方法 是否開啟事務 狀态 是否復原
doPreSomething 開啟事務 失敗 全部復原
methodB A内部直接加入事務,不單獨開啟,單獨調用開啟 失敗 全部復原
doSufSomething 失敗 全部復原

所有方法在同一個事務中運作,要麼一起成功送出事務,要麼一起復原事務,如果單獨執行,各自單獨開啟各自事務。

2、PROPAGATION_REQUIRED_NEW

方法 是否開啟事務 狀态 是否復原
doPreSomething 開啟事務 失敗 隻復原方法A自己
methodB 開啟事務 失敗 隻復原方法B自己
doSufSomething 失敗 值復原方法A自己

PROPAGATION_REQURIED_NEW所有方法使用各自的事務,各自送出或者復原各自的事務,互相之間不會造成影響。

如果嵌套執行的方法要求各自事務獨立,不能進行互相影響,則選擇本事務傳播級别。

3、PROPAGATION_SUPPORTS|

方法 是否開啟事務 狀态 是否復原
doPreSomething 開啟事務 失敗 全部復原
methodB A内部加入事務不單獨開啟,單獨調用不開啟 失敗 全部復原
doSufSomething 失敗 全部復原

如果嵌套執行的方法要求一起執行成功或者一起復原,單獨執行時候以非事務方式執行,則選擇該事物傳播級别。

4、PROPAGATION_NOT_SUPPORTED

方法 是否開啟事務 狀态 是否復原
doPreSomething 開啟事務 失敗 隻復原A自己
methodB A内部挂起A的事務狀态執行事務以非,不單獨開啟,單獨調用不開啟 失敗 不做任何復原
doSufSomething 失敗 隻復原A自己

如果嵌套執行的方法要求内部嵌套方法不會對外部方法事務造成影響并且内部方法不需要事務,單獨執行時候以非事務方式執行,則選擇該事物傳播級别。

5、PROPAGATION_MANDATORY

方法 是否開啟事務 狀态 是否復原
doPreSomething 開啟事務 失敗 全部復原
methodB A内部加入A的事務,不單獨開啟,單獨調用跑錯 失敗 全部復原
doSufSomething 失敗 全部復原

如果嵌套執行的方法要求一起執行成功或者一起復原,單獨執行時候不允許以非事務方式執行,則選擇該事物傳播級别。

6、PROPAGATION_NEVER

方法 是否開啟事務 狀态 是否復原
doPreSomething 開啟事務 失敗 全部復原
methodB A存着事務直接抛錯,不單獨開啟 失敗 全部復原
doSufSomething 失敗 全部復原

如果嵌套執行的方法要求内部方法不允許在事務中執行,單獨執行時候必須以非事務方式執行,則選擇該事物傳播級别。

7、PROPAGATION_NESTED

方法 是否開啟事務 狀态 是否復原
doPreSomething 開啟事務 失敗 全部復原
methodB A存着事務就直接加入A事務,不存在開啟事務 失敗 隻復原B自己
doSufSomething 失敗 全部復原

如果嵌套執行的方法要求内部方法出錯隻復原自己,外部方法執行失敗復原所有,單獨執行時候自動開啟一個執行,則選擇該事物傳播級别。