最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Java中Spring對事務(wù)的支持詳解

 更新時間:2023年07月11日 11:04:08   作者:藍(lán)云飄飄2366  
這篇文章主要介紹了Java中Spring對事務(wù)的支持詳解,Spring對事務(wù)的支持有兩種方式,一是自己編寫事務(wù),精確控制事務(wù)的邊界,二是采用聲明事務(wù)的方式,使用AOP來完成,需要的朋友可以參考下

事務(wù)屬性

  • 事務(wù)傳播行為;--Propagation(本文重點解讀事務(wù)傳播行為)
  • 事務(wù)隔離級別;--Isolation
  • 事務(wù)超時;--timeout
  • 只讀事務(wù);--readOnly
  • 設(shè)置出現(xiàn)哪些異常回滾事務(wù);--rollbackFor
  • 設(shè)置出現(xiàn)哪些異常不回滾事務(wù);--noRollbackFor

事務(wù)的傳播行為

一、什么是事務(wù)的傳播行為

在service類中有a()方法和b()方法,a()方法上有事務(wù),b()方法上也有事務(wù),當(dāng)a()方法執(zhí)行過程中調(diào)用了b()方法,事務(wù)是如何傳遞的?合并到一個事務(wù)里?還是開啟一個新的事務(wù)?這就是事務(wù)傳播行為。

注意:以下事務(wù)傳播屬性都是打在內(nèi)部方法b()方法上的事務(wù)注解

二、7種事務(wù)傳播行為

Spring 可以通過 @Transactional 注解的 propagation 屬性來設(shè)置不同的傳播行為策略。

Spring 為此提供了一個枚舉類 Propagation,源碼如下:

package org.springframework.transaction.annotation;
import org.springframework.transaction.TransactionDefinition;
public enum Propagation {
   /**
    * 需要事務(wù),它是默認(rèn)傳播行為,如果當(dāng)前存在事務(wù),就沿用當(dāng)前事務(wù),
    * 否則新建一個事務(wù)運行內(nèi)部方法
    */
   REQUIRED(TransactionDefinition.PROPAGATION_REQUIRED),
   /**
    * 支持事務(wù),如果當(dāng)前存在事務(wù),就沿用當(dāng)前事務(wù),
    * 如果不存在,則繼續(xù)采用無事務(wù)的方式運行內(nèi)部方法
    */
   SUPPORTS(TransactionDefinition.PROPAGATION_SUPPORTS),
   /**
    * 必須使用事務(wù),如果當(dāng)前沒有事務(wù),則會拋出異常,
    * 如果存在當(dāng)前事務(wù),則沿用當(dāng)前事務(wù)
    */
   MANDATORY(TransactionDefinition.PROPAGATION_MANDATORY),
   /**
    * 無論當(dāng)前事務(wù)是否存在,都會創(chuàng)建新事務(wù)運行方法,
    * 這樣新事務(wù)就可以擁有新的鎖和隔離級別等特性,與當(dāng)前事務(wù)相互獨立
    */
   REQUIRES_NEW(TransactionDefinition.PROPAGATION_REQUIRES_NEW),
   /**
    * 不支持事務(wù),當(dāng)前存在事務(wù)時,將掛起事務(wù),運行方法
    */
   NOT_SUPPORTED(TransactionDefinition.PROPAGATION_NOT_SUPPORTED),
   /**
    * 不支持事務(wù),如果當(dāng)前方法存在事務(wù),則拋出異常,否則繼續(xù)使用無事務(wù)機制運行
    */
   NEVER(TransactionDefinition.PROPAGATION_NEVER),
   /**
    * 在當(dāng)前方法調(diào)用內(nèi)部方法時,如果內(nèi)部方法發(fā)生異常,
    * 只回滾內(nèi)部方法執(zhí)行過的 SQL ,而不回滾當(dāng)前方法的事務(wù)
    */
   NESTED(TransactionDefinition.PROPAGATION_NESTED);
......
}

接下來我們通過對其中三種最常用的(REQUIRED、REQUIRES_NEW、NESTED)策略進(jìn)行對比來更深入的理解。以下測試均在外部方法開啟事務(wù)的情況下進(jìn)行,因為在外部沒有事務(wù)的情況下,三者都會新建事務(wù),效果一樣。 

1. REQUIRED

當(dāng)內(nèi)部方法的事務(wù)傳播行為設(shè)置為 REQUIRED 時,內(nèi)部方法會加入外部方法的事務(wù)。我們在 UserServiceImpl 中添加如下方法:  

@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {
   @Autowired
   private UserMapper mapper;
   @Override
   @Transactional(propagation = Propagation.REQUIRED)
   public void addWithRequired(User user) {
       mapper.insert(user);
  }
   @Override
   @Transactional(propagation = Propagation.REQUIRED)
   public void addWithRequiredAndException(User user) {
       mapper.insert(user);
       throw new RuntimeException();
  }
}

創(chuàng)建 TransactionServiceImpl 類,并添加如下方法:

@Slf4j
@Service
public class TransactionServiceImpl implements TransactionService {
    @Autowired
    private UserService userService;
    @Override
    public void noTransaction_required_required_externalException() {
        User xiaoShui = new User().setName("小水");
        User xiaoJing = new User().setName("小鏡");
        userService.addWithRequired(xiaoShui);
        userService.addWithRequired(xiaoJing);
        throw new RuntimeException();
    }
    @Override
    public void noTransaction_required_requiredException() {
        User xiaoShui = new User().setName("小水");
        User xiaoJing = new User().setName("小鏡");
        userService.addWithRequired(xiaoShui);
        userService.addWithRequiredAndException(xiaoJing);
    }
    @Override
    @Transactional
    public void transaction_required_required_externalException() {
        User xiaoShui = new User().setName("小水");
        User xiaoJing = new User().setName("小鏡");
        userService.addWithRequired(xiaoShui);
        userService.addWithRequired(xiaoJing);
        throw new RuntimeException();
    }
    @Override
    @Transactional
    public void transaction_required_requiredException() {
        User xiaoShui = new User().setName("小水");
        User xiaoJing = new User().setName("小鏡");
        userService.addWithRequired(xiaoShui);
        userService.addWithRequiredAndException(xiaoJing);
    }
    @Override
    @Transactional
    public void transaction_required_requiredException_try() {
        User xiaoShui = new User().setName("小水");
        User xiaoJing = new User().setName("小鏡");
        userService.addWithRequired(xiaoShui);
        try {
            userService.addWithRequiredAndException(xiaoJing);
        } catch (Exception e) {
            log.error("發(fā)生異常,事務(wù)回滾!");
        }
    }
}

結(jié)果分析如下表所示:

前面四種情況都比較好理解,很多人不能理解最后一種情況:我都 try-catch 了你還想怎樣?這里的關(guān)鍵點在于所有方法都處于同一個事務(wù)中,此時「小鏡」的插入方法發(fā)生異常,那么這個方法所在的事務(wù)就會被 Spring 設(shè)置為 rollback 狀態(tài)。因為異常被 catch 了,所以外部方法執(zhí)行完要進(jìn)行 commit 操作,這時卻發(fā)現(xiàn)當(dāng)前事務(wù)已經(jīng)處于 rollback 狀態(tài)了,雖然它不知道哪里出了問題,但也只能聽從指揮,回滾所有操作了。

PS:由于外部方法不開啟事務(wù)的情況,在每種傳播行為下結(jié)果都是類似的,所以后面不再給出示例。

2. REQUIRES_NEW

當(dāng)內(nèi)部方法的傳播行為設(shè)置為 REQUIRES_NEW 時,內(nèi)部方法會先將外部方法的事務(wù)掛起,然后開啟一個新的事務(wù) 。在 UserServiceImpl 中添加如下方法(UserServiceImpl 類中上面的方法還在哦):

@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {
    ...
    @Override
    @Transactional(propagation = Propagation.REQUIRES_NEW)
    public void addWithRequiredNew(User user) {
        mapper.insert(user);
    }
    @Override
    @Transactional(propagation = Propagation.REQUIRES_NEW)
    public void addWithRequiredNewAndException(User user) {
        mapper.insert(user);
        throw new RuntimeException();
    }
}

在 TransactionServiceImpl 中添加如下方法:

@Slf4j
@Service
public class TransactionServiceImpl implements TransactionService {
    ...
    @Override
    @Transactional
    public void transaction_required_requiredNew_externalException() {
        User xiaoShui = new User().setName("小水");
        User xiaoJing = new User().setName("小鏡");
        userService.addWithRequired(xiaoShui);
        userService.addWithRequiredNew(xiaoJing);
        throw new RuntimeException();
    }
    @Override
    @Transactional
    public void transaction_required_requiredNew_requiredNewException() {
        User xiaoShui = new User().setName("小水");
        User xiaoJing = new User().setName("小鏡");
        User shuiJing = new User().setName("水鏡");
        userService.addWithRequired(xiaoShui);
        userService.addWithRequiredNew(xiaoJing);
        userService.addWithRequiredNewAndException(shuiJing);
    }
    @Override
    @Transactional
    public void transaction_required_requiredNewException_try() {
        User xiaoShui = new User().setName("小水");
        User xiaoJing = new User().setName("小鏡");
        User shuiJing = new User().setName("水鏡");
        userService.addWithRequired(xiaoShui);
        userService.addWithRequiredNew(xiaoJing);
        try {
            userService.addWithRequiredNewAndException(shuiJing);
        } catch (Exception e) {
            log.error("發(fā)生異常,事務(wù)回滾!");
        }
    }
}

結(jié)果分析如下表所示:

3. NESTED

當(dāng)內(nèi)部方法的傳播行為設(shè)置為 NESTED 時,內(nèi)部方法會開啟一個新的嵌套事務(wù)(子事務(wù))。在 UserServiceImpl 中添加如下方法:

@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {
    ...
    @Override
    @Transactional(propagation = Propagation.NESTED)
    public void addWithNested(User user) {
        mapper.insert(user);
    }
    @Override
    @Transactional(propagation = Propagation.NESTED)
    public void addWithNestedAndException(User user) {
        mapper.insert(user);
        throw new RuntimeException();
    }
}

在 TransactionServiceImpl 中添加如下方法:  

@Slf4j
@Service
public class TransactionServiceImpl implements TransactionService {
    ...
    @Override
    @Transactional
    public void transaction_nested_nested_externalException() {
        User xiaoShui = new User().setName("小水");
        User xiaoJing = new User().setName("小鏡");
        userService.addWithNested(xiaoShui);
        userService.addWithNested(xiaoJing);
        throw new RuntimeException();
    }
    @Override
    @Transactional
    public void transaction_nested_nestedException() {
        User xiaoShui = new User().setName("小水");
        User xiaoJing = new User().setName("小鏡");
        userService.addWithNested(xiaoShui);
        userService.addWithNestedAndException(xiaoJing);
    }
    @Override
    @Transactional
    public void transaction_nested_nestedException_try() {
        User xiaoShui = new User().setName("小水");
        User xiaoJing = new User().setName("小鏡");
        User shuiJing = new User().setName("水鏡");
        userService.addWithRequired(xiaoShui);
        userService.addWithNested(xiaoJing);
        try {
            userService.addWithNestedAndException(shuiJing);
        } catch (Exception e) {
            log.error("發(fā)生異常,事務(wù)回滾!",e);
        }
    }
}

結(jié)果分析如下表所示:

每個 NESTED 事務(wù)執(zhí)行前會將當(dāng)前操作保存下來,叫做 savepoint (保存點),如果當(dāng)前 NESTED 事務(wù)執(zhí)行失敗,則回滾到之前的保存點,保存點使得子事務(wù)的回滾不對主事務(wù)造成影響。NESTED 事務(wù)在外部事務(wù)提交以后自己才會提交。

4. 總結(jié)

REQUIRES_NEW 最為簡單,不管當(dāng)前有無事務(wù),它都會開啟一個全新事務(wù),既不影響外部事務(wù),也不會影響其他內(nèi)部事務(wù),真正的井水不犯河水,堅定而獨立。

REQUIRED 在沒有外部事務(wù)的情況下,會開啟一個獨立的新事務(wù),且不會對其他同級事務(wù)造成影響;而當(dāng)存在外部事務(wù)的情況下,則會與外部事務(wù)同生共死。

NESTED 在沒有外部事務(wù)的情況下與 REQUIRED 效果相同;而當(dāng)存在外部事務(wù)的情況下,當(dāng)外部事務(wù)回滾時,它會創(chuàng)建一個嵌套事務(wù)(子事務(wù))。外部事務(wù)回滾時,子事務(wù)會跟著回滾;但子事務(wù)的回滾不會對外部事務(wù)和其他同級事務(wù)造成影響。

三、事務(wù)的傳播行為(理解記憶)

到此這篇關(guān)于Java中Spring對事務(wù)的支持詳解的文章就介紹到這了,更多相關(guān)Spring對事務(wù)的支持內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 史上最全maven中的pom詳述

    史上最全maven中的pom詳述

    pom是maven的基本工作單元,它是一個XML文件,其中包含有關(guān)項目的信息以及Maven用于構(gòu)建項目的配置詳細(xì)信息,本文給大家介紹maven中的pom詳述,感興趣的朋友一起看看吧
    2025-10-10
  • Java結(jié)構(gòu)型模式中的組合模式詳解

    Java結(jié)構(gòu)型模式中的組合模式詳解

    組合模式,又叫部分整體模式,它創(chuàng)建了對象組的數(shù)據(jù)結(jié)構(gòu)組合模式使得用戶對單個對象和組合對象的訪問具有一致性。本文將通過示例為大家詳細(xì)介紹一下組合模式,需要的可以參考一下
    2023-02-02
  • 5分鐘快速創(chuàng)建spring boot項目的完整步驟

    5分鐘快速創(chuàng)建spring boot項目的完整步驟

    這篇文章主要給大家介紹了關(guān)于通過5分鐘快速創(chuàng)建spring boot項目的完整步驟,文中通過示例代碼介紹的非常詳細(xì),對大家學(xué)習(xí)或者使用spring boot具有一定的參考學(xué)習(xí)價值,需要的朋友們下面來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-06-06
  • Java中jar包運行后顯示:沒有主清單屬性的解決方案

    Java中jar包運行后顯示:沒有主清單屬性的解決方案

    這篇文章主要介紹了Java中jar包運行后顯示:沒有主清單屬性的解決方案,文中給大家分析了三個主要原因,并通過代碼示例和圖文講解的非常詳細(xì),需要的朋友可以參考下
    2024-04-04
  • Spring 日志規(guī)范及作用

    Spring 日志規(guī)范及作用

    日志是在系統(tǒng)運行過程中關(guān)鍵的節(jié)點的數(shù),這個些日志的記錄方便當(dāng)系統(tǒng)出現(xiàn)問題方便問題查找,這篇文章主要介紹了Spring 日志規(guī)范及作用,需要的朋友可以參考下
    2024-03-03
  • 解決IDEA占用C盤空間過大的問題

    解決IDEA占用C盤空間過大的問題

    這篇文章主要介紹了解決IDEA占用C盤空間過大的問題,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2021-02-02
  • Java實現(xiàn)提取QSV文件視頻內(nèi)容

    Java實現(xiàn)提取QSV文件視頻內(nèi)容

    QSV是一種加密的視頻文件格式。是愛奇藝公司研發(fā)的一種視頻文件格式,這篇文章主要為大家介紹了如何利用Java實現(xiàn)提取QSV文件視頻內(nèi)容,感興趣的可以了解一下
    2023-03-03
  • SpringCloud Zuul服務(wù)功能與使用方法解析

    SpringCloud Zuul服務(wù)功能與使用方法解析

    這篇文章主要介紹了SpringCloud Zuul服務(wù)功能與使用方法解析,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2020-05-05
  • 關(guān)于SpringCloud灰度發(fā)布的實現(xiàn)

    關(guān)于SpringCloud灰度發(fā)布的實現(xiàn)

    這篇文章主要介紹了關(guān)于SpringCloud灰度發(fā)布的實現(xiàn),灰度發(fā)布又稱金絲雀發(fā)布,是在系統(tǒng)升級的時候能夠平滑過渡的一種發(fā)布方式,灰度發(fā)布可以保證整體系統(tǒng)的穩(wěn)定,在初始灰度的時候就可以發(fā)現(xiàn)、調(diào)整問題,以保證其影響度,需要的朋友可以參考下
    2023-08-08
  • SpringCloud之Zuul網(wǎng)關(guān)原理及其配置講解

    SpringCloud之Zuul網(wǎng)關(guān)原理及其配置講解

    這篇文章主要介紹了SpringCloud之Zuul網(wǎng)關(guān)原理及其配置講解,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-03-03

最新評論

昌图县| 天门市| 永年县| 鄂托克旗| 岐山县| 富民县| 潼关县| 都昌县| 鱼台县| 苏尼特右旗| 温宿县| 邵阳市| 安仁县| 大化| 怀远县| 阆中市| 潮州市| 泾川县| 武乡县| 时尚| 平潭县| 化州市| 白朗县| 黄龙县| 东莞市| 无为县| 灌南县| 砀山县| 托克托县| 唐山市| 晋城| 安龙县| 呼和浩特市| 金塔县| 武平县| 贡山| 阜康市| 禄丰县| 和林格尔县| 昆明市| 永和县|