SpringBoot 事務(@Transactional)整合
- Spring boot 事務整合
-
- 業務分析
- 實戰編碼
- 資料庫的四種隔離級别
- Spring中七種事務傳播行為
Spring boot 事務整合
spring boot 事務是怎麼控制的呢?就是我們熟知的
@Transactional
注解了
業務分析
讓代碼更新資訊後抛出異常,看看資料會不會復原
實戰編碼
修改更新使用者資訊接口抛出一個異常
@PutMapping("/user")
@Transactional(rollbackFor = Exception.class)
public String updateUser(@RequestBody ApiUserVO vo) {
int flag = userService.updateUser(vo);
int i =1/0;
if (flag <= 0) {
return "修改失敗";
}
return "修改成功";
}
抛出異常後資料庫并未進行修改;
@Transactional 異常不復原幾種原因
- @Transactional是基于AOP動态代理做的,是以方法必須是public;其他的修飾符不生效。
- Spring事務控制器在catch裡面做了判斷隻有RuntimeException或者錯誤資訊的時候才會復原,故不是RuntimeException的異常不會復原。
Transactional的異常控制,預設是Check Exception 不復原,unCheck Exception復原 如果配置了rollbackFor 和 noRollbackFor 且兩個都是用同樣的異常,那麼遇到該異常,還是復原 rollbackFor 和noRollbackFor 配置也許不會含蓋所有異常,對于遺漏的按照Check Exception 不復原,unCheck Exception復原。
資料庫的四種隔離級别
資料庫一共有如下四種隔離級别:
-
Read uncommitted
讀未送出
在該級别下,一個事務對一行資料修改的過程中,不允許另一個事務對該行資料進行修改,但允許另一個事務對該行資料讀。
是以本級别下,不會出現更新丢失,但會出現髒讀、不可重複讀。
-
Read committed
讀已送出
在該級别下,未送出的寫事務不允許其他事務通路該行,是以不會出現髒讀;但是讀取資料的事務允許其他事務的通路該行資料,是以會出現不可重複讀的情況。
-
Repeatable read
可重複讀
在該級别下,讀事務禁止寫事務,但允許讀事務,是以不會出現同一事務兩次讀到不同的資料的情況(不可重複讀),且寫事務禁止其他一切事務。
-
該級别要求所有事務都必須串行執行,是以能避免一切因并發引起的問題,但效率很低。Serializable 序列化
隔離級别越高,越能保證資料的完整性和一緻性,但是對并發性能的影響也越大。對于多數應用程式,可以優先考慮把資料庫系統的隔離級别設為Read Committed。它能夠避免髒讀取,而且具有較好的并發性能。盡管它會導緻不可重複讀、幻讀和第二類丢失更新這些并發問題,在可能出現這類問題的個别場合,可以由應用程式采用悲觀鎖或樂觀鎖來控制。
隔離級别 | 髒讀 | 不可重複讀 | 幻讀 |
---|---|---|---|
讀未送出(Read uncommitted) | √ | √ | √ |
讀已送出(Read committed) | × | √ | √ |
可重複讀(Repeatable read) | × | × | √ |
可串行化(Serializable ) | × | × | × |
Spring中七種事務傳播行為
序号 | 事務傳播行為類型 | 說明 |
---|---|---|
1 | PROPAGATION_REQUIRED | 如果目前沒有事務,就建立一個事務,如果已經存在一個事務中,加入到這個事務中。這是最常見的選擇。 |
2 | PROPAGATION_SUPPORTS | 支援目前事務,如果目前沒有事務,就以非事務方式執行 |
3 | PROPAGATION_MANDATORY | 使用目前的事務,如果目前沒有事務,就抛出異常。 |
4 | PROPAGATION_REQUIRES_NEW | 建立事務,如果目前存在事務,把目前事務挂起。 |
5 | PROPAGATION_NOT_SUPPORTED | 以非事務方式執行操作,如果目前存在事務,就把目前事務挂起。 |
6 | PROPAGATION_NEVER | 以非事務方式執行,如果目前存在事務,則抛出異常。 |
7 | PROPAGATION_NESTED | 如果目前存在事務,則在嵌套事務内執行。如果目前沒有事務,則執行與PROPAGATION_REQUIRED類似的操作。 |
可以看出1、2、3為一組,都表現對目前事務的支援,不同的在于目前不存在事務的處理方式;4、5、6為一組,都表現對目前事務的不支援,不同的在于目前有事務的處理方式。然後7單獨一組。
舉個小栗子,比如有一個service中有方法A,調用了方法B,方法B的傳播行為是PROPAGATION_REQUIRED,那麼如果方法A的傳播行為也是PROPAGATION_REQUIRED,方法A運作的時候,開啟了一個事務,方法A中執行到方法B的時候,察覺到目前已經有事務了,方法B就不會再建立新的事務,直接包含在方法A的事務當中。