天天看點

SpringBoot 事務(@Transactional)整合Spring boot 事務整合資料庫的四種隔離級别Spring中七種事務傳播行為

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 異常不復原幾種原因

  1. @Transactional是基于AOP動态代理做的,是以方法必須是public;其他的修飾符不生效。
  2. 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的事務當中。