欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Spring的@Transactional嵌套解讀

 更新時(shí)間:2024年11月08日 15:18:03   作者:Lanje?Wang  
本文通過(guò)詳細(xì)測(cè)試,探究了Spring的@Transactional注解在事務(wù)嵌套和局部回滾場(chǎng)景下的行為表現(xiàn),文中通過(guò)多個(gè)測(cè)試案例,闡述了不同傳播行為(如REQUIRES_NEW)對(duì)事務(wù)嵌套處理的影響,以及rollbackFor屬性在異常管理中的作用和限制,通過(guò)實(shí)驗(yàn)總結(jié)

事務(wù)嵌套局部回滾的問(wèn)題,很是費(fèi)解。

本文將做一個(gè)詳細(xì)的測(cè)試,加強(qiáng)對(duì)Spring的@Transactional 理解和使用

1、兩個(gè)單獨(dú)不干擾事務(wù)

	@RequestMapping("/test")
    public void test() {
        LoveFile test1 = new LoveFile();
        test1.setFileUuid(get32Uuid());
        test1.setFileName("test1");
        loveFileService.test1(test1);
        LoveFile test2 = new LoveFile();
        test2.setFileUuid(null);
        test2.setFileName("test2");
        loveFileService.test2(test2);
    }
    @Override
    @Transactional
    public void test1(LoveFile loveFile) {
        mapper.insertSelective(loveFile);

    }
    @Override
    @Transactional
    public void test2(LoveFile loveFile) {
        mapper.insertSelective(loveFile);
    }

由于我給第二個(gè)test2插入主鍵為空,報(bào)錯(cuò)。因此庫(kù)里只有一條

總結(jié):兩個(gè)單獨(dú)事務(wù)互不干擾。錯(cuò)了就是錯(cuò)了,很好理解

2、普通嵌套事務(wù)

	@RequestMapping("/test")
    @Transactional
    public void test() {
        LoveFile test1 = new LoveFile();
        test1.setFileUuid(get32Uuid());
        test1.setFileName("test1");
        loveFileService.test1(test1);
        LoveFile test2 = new LoveFile();
        test2.setFileUuid(null);
        test2.setFileName("test2");
        loveFileService.test2(test2);
    }

子事務(wù)不變,刪除剛才的數(shù)據(jù)后,測(cè)試。

庫(kù)里空空。

總結(jié):加在外層的事務(wù)起了作用,在test2報(bào)錯(cuò)時(shí)回滾了test1

3、嵌套事務(wù)、三個(gè)子事務(wù)中間一個(gè)加(propagation = Propagation.REQUIRES_NEW)

Propagation取值:

  • REQUIRED(默認(rèn)值):在有transaction狀態(tài)下執(zhí)行;如當(dāng)前沒(méi)有transaction,則創(chuàng)建新的transaction;
  • SUPPORTS:如當(dāng)前有transaction,則在transaction狀態(tài)下執(zhí)行;如果當(dāng)前沒(méi)有transaction,在無(wú)transaction狀態(tài)下執(zhí)行;
  • MANDATORY:必須在有transaction狀態(tài)下執(zhí)行,如果當(dāng)前沒(méi)有transaction,則拋出異常IllegalTransactionStateException;
  • REQUIRES_NEW:創(chuàng)建新的transaction并執(zhí)行;如果當(dāng)前已有transaction,則將當(dāng)前transaction掛起;
  • NOT_SUPPORTED:在無(wú)transaction狀態(tài)下執(zhí)行;如果當(dāng)前已有transaction,則將當(dāng)前transaction掛起;
  • NEVER:在無(wú)transaction狀態(tài)下執(zhí)行;如果當(dāng)前已有transaction,則拋出異常IllegalTransactionStateException。

本文重點(diǎn)研究 REQUIRES_NEW

@RequestMapping("/test")
    @Transactional
    public void test() {
        LoveFile test1 = new LoveFile();
        test1.setFileUuid(get32Uuid());
        test1.setFileName("test1");
        loveFileService.test1(test1);
        LoveFile test3 = new LoveFile();
        test3.setFileUuid(get32Uuid());
        test3.setFileName("test3");
        loveFileService.test3(test3);
        LoveFile test2 = new LoveFile();
        test2.setFileUuid(null);
        test2.setFileName("test2");
        loveFileService.test2(test2);
    }
@Override
    @Transactional
    public void test1(LoveFile loveFile) {
        mapper.insertSelective(loveFile);
    }
    @Override
    @Transactional
    public void test2(LoveFile loveFile) {
        mapper.insertSelective(loveFile);
    }
    @Override
    @Transactional(propagation = Propagation.REQUIRES_NEW)
    public void test3(LoveFile loveFile) {
        mapper.insertSelective(loveFile);
    }

REQUIRES_NEW官方文檔解釋:

Create a new transaction, and suspend the current transaction if one exists.

意思是,創(chuàng)建一個(gè)新事務(wù),如果當(dāng)前存在事務(wù),將這個(gè)事務(wù)掛起。

也就是說(shuō)test3,是獨(dú)立于外層事務(wù)的單獨(dú)的事務(wù),他已經(jīng)掛起的外層事務(wù),他要把自己的問(wèn)題處理完再去管別人。

因此結(jié)果是

總結(jié):不給子事務(wù)加(propagation = Propagation.REQUIRES_NEW),相當(dāng)于加入了外層事務(wù)。加了則當(dāng)做新的子事務(wù)。

test2報(bào)錯(cuò)了,影響了test1 ,卻不能影響test3,已經(jīng)說(shuō)明了此問(wèn)題

4、嵌套事務(wù)、三個(gè)子事務(wù)中間一個(gè)加(propagation = Propagation.REQUIRES_NEW),偏偏出錯(cuò)了

	@RequestMapping("/test")
    @Transactional
    public void test() {
        LoveFile test1 = new LoveFile();
        test1.setFileUuid(get32Uuid());
        test1.setFileName("test1");
        loveFileService.test1(test1);
        LoveFile test3 = new LoveFile();
        test3.setFileUuid(null);
        test3.setFileName("test3");
        loveFileService.test3(test3);
        LoveFile test2 = new LoveFile();
        test2.setFileUuid(get32Uuid());
        test2.setFileName("test2");
        loveFileService.test2(test2);
    }

我把test3主鍵為空,因此他會(huì)有SQLException。來(lái)研究下,他會(huì)不會(huì)影響整體。

總結(jié): 雖然他是開(kāi)辟的新事物,但是出錯(cuò)了,還是會(huì)牽連整體的

至此,(propagation = Propagation.REQUIRES_NEW) 已經(jīng)解釋清楚了。

我覺(jué)得子事務(wù),不加這個(gè)東西的話不叫子事務(wù)。不加的話直接加入了外層事務(wù)。那還要個(gè)單單 @Transactional何用?

建議大家對(duì)子事務(wù)都加上這條件。

rollbackFor官方文檔解釋:

在@Transactional注解中如果不配置rollbackFor屬性,那么事物只會(huì)在遇到RuntimeException的時(shí)候才會(huì)回滾,加上rollbackFor=Exception.class,可以讓事物在遇到非運(yùn)行時(shí)異常時(shí)也回滾

5、rollbackFor了一個(gè)異常,卻會(huì)報(bào)另外異常

@RequestMapping("/test")
    @Transactional
    public void test() {
        LoveFile test1 = new LoveFile();
        test1.setFileUuid(get32Uuid());
        test1.setFileName("test1");
        loveFileService.test1(test1);
        LoveFile test3 = new LoveFile();
        test3.setFileUuid(null);
        test3.setFileName("test3");
        loveFileService.test3(test3);
        LoveFile test2 = new LoveFile();
        test2.setFileUuid(get32Uuid());
        test2.setFileName("test2");
        loveFileService.test2(test2);
    }
 @Override
    @Transactional
    public void test1(LoveFile loveFile) {
        mapper.insertSelective(loveFile);
    }
    @Override
    @Transactional
    public void test2(LoveFile loveFile) {
        mapper.insertSelective(loveFile);
    }
    @Override
    @Transactional(rollbackFor=SQLException.class,propagation = Propagation.REQUIRES_NEW)
    public void test3(LoveFile loveFile) {
        int  a = 1/0;
       // mapper.insertSelective(loveFile);
    }

這個(gè)test3,一定會(huì)報(bào) by zero,他會(huì)報(bào)錯(cuò),我來(lái)測(cè)試下,他會(huì)不會(huì)回滾,影響他人。

如此是影響了。

因?yàn)橥鈱邮聞?wù)沒(méi)有聲明異常,他看到一個(gè)內(nèi)部報(bào)by zero 了,而自己是RuntimeException,包含在內(nèi)。因此自己回滾了。

test1 是直接加入整體的。沒(méi)加出數(shù)據(jù),就說(shuō)明了此問(wèn)題。

我其實(shí)是像測(cè)試,test3是否回滾,這個(gè)測(cè)試案例不合適。

@RequestMapping("/test")
    @Transactional
    public void test() {
        LoveFile test1 = new LoveFile();
        test1.setFileUuid(get32Uuid());
        test1.setFileName("test1");
        loveFileService.test1(test1);
        LoveFile test3 = new LoveFile();
        test3.setFileUuid(get32Uuid());
        test3.setFileName("test3");
        loveFileService.test3(test3);
        LoveFile test2 = new LoveFile();
        test2.setFileUuid(get32Uuid());
        test2.setFileName("test2");
        loveFileService.test2(test2);
    }
   @Override
    @Transactional
    public void test1(LoveFile loveFile) {
        mapper.insertSelective(loveFile);
    }
    @Override
    @Transactional
    public void test2(LoveFile loveFile) {
        mapper.insertSelective(loveFile);
    }
    @Override
    @Transactional(rollbackFor=SQLException.class,propagation = Propagation.REQUIRES_NEW)
    public void test3(LoveFile loveFile) {
        mapper.insertSelective(loveFile);
        int  a = 1/0;
    }

我給了test3 正常的主鍵,讓他添加成功,卻在后面 by zero .因?yàn)槲艺J(rèn)為他不會(huì)回滾,這次應(yīng)該是test3加進(jìn)去了,test1和test2被外層事務(wù)回滾。

但是結(jié)果是:

我又做了一些測(cè)試,發(fā)現(xiàn)rollbackFor=SQLException.class 這樣的聲明一個(gè)特定的異常沒(méi)有任何效果。

rollbackFor 用途不大,就是聲明rollbackFor=Exception.class 時(shí)比 RuntimeException 廣一些。

其他時(shí)用途不大。

如果想讓特定異常不回滾,還不如用 try catch。只要異常被catch住,不被方法知道,就不會(huì)出現(xiàn)error ,也就不會(huì)回滾。

總結(jié)

以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。

相關(guān)文章

  • Jmeter后置處理器實(shí)現(xiàn)過(guò)程及方法應(yīng)用

    Jmeter后置處理器實(shí)現(xiàn)過(guò)程及方法應(yīng)用

    這篇文章主要介紹了Jmeter后置處理器實(shí)現(xiàn)過(guò)程及方法應(yīng)用,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-09-09
  • SSH框架網(wǎng)上商城項(xiàng)目第26戰(zhàn)之訂單支付后發(fā)送短信提醒

    SSH框架網(wǎng)上商城項(xiàng)目第26戰(zhàn)之訂單支付后發(fā)送短信提醒

    這篇文章主要為大家詳細(xì)介紹了SSH框架網(wǎng)上商城項(xiàng)目第26戰(zhàn)之訂單支付后發(fā)送短信提醒,感興趣的小伙伴們可以參考一下
    2016-06-06
  • Mybatis圖文并茂講解分頁(yè)插件

    Mybatis圖文并茂講解分頁(yè)插件

    使用過(guò)mybatis的人都知道,mybatis本身就很小且簡(jiǎn)單,sql寫在xml里,統(tǒng)一管理和優(yōu)化。缺點(diǎn)當(dāng)然也有,比如我們使用過(guò)程中,要使用到分頁(yè),如果用最原始的方式的話,1.查詢分頁(yè)數(shù)據(jù),2.獲取分頁(yè)長(zhǎng)度,也就是說(shuō)要使用到兩個(gè)方法才能完成分頁(yè)
    2022-07-07
  • Java之關(guān)于基本數(shù)據(jù)類型和引用數(shù)據(jù)類型的存放位置

    Java之關(guān)于基本數(shù)據(jù)類型和引用數(shù)據(jù)類型的存放位置

    這篇文章主要介紹了Java之關(guān)于基本數(shù)據(jù)類型和引用數(shù)據(jù)類型的存放位置,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-07-07
  • 簡(jiǎn)單了解Java編程中對(duì)異常處理的運(yùn)用

    簡(jiǎn)單了解Java編程中對(duì)異常處理的運(yùn)用

    這篇文章主要簡(jiǎn)單介紹了Java編程中對(duì)異常處理的運(yùn)用,是Java入門學(xué)習(xí)中的基礎(chǔ)知識(shí),需要的朋友可以參考下
    2015-09-09
  • Java中遍歷數(shù)組使用foreach循環(huán)還是for循環(huán)?

    Java中遍歷數(shù)組使用foreach循環(huán)還是for循環(huán)?

    這篇文章主要介紹了Java中遍歷數(shù)組使用foreach循環(huán)還是for循環(huán)?本文著重講解for語(yǔ)句的語(yǔ)法并給出使用實(shí)例,同時(shí)總結(jié)出盡量使用foreach語(yǔ)句遍歷數(shù)組,需要的朋友可以參考下
    2015-06-06
  • java this引用逃逸詳解

    java this引用逃逸詳解

    這篇文章主要介紹了java this引用逃逸的相關(guān)資料,幫助大家更好的理解和使用Java,感興趣的朋友可以了解下
    2020-12-12
  • SpringBoot中Starter的作用小結(jié)

    SpringBoot中Starter的作用小結(jié)

    這篇文章主要介紹了SpringBoot中Starter的作用小結(jié),Starter其實(shí)就是Spring針對(duì)不用的開(kāi)發(fā)場(chǎng)景,給我們提供的“套餐”。今天就通過(guò)實(shí)例代碼給大家介紹Starter,感興趣的朋友一起看看吧
    2021-10-10
  • Mybatis?TypeHandler接口及繼承關(guān)系示例解析

    Mybatis?TypeHandler接口及繼承關(guān)系示例解析

    這篇文章主要為大家介紹了Mybatis?TypeHandler接口及繼承關(guān)系示例解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-02-02
  • Idea中添加Maven項(xiàng)目支持scala的詳細(xì)步驟

    Idea中添加Maven項(xiàng)目支持scala的詳細(xì)步驟

    這篇文章主要介紹了Idea中添加Maven項(xiàng)目支持scala,本文通過(guò)圖文并茂的形式給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2023-03-03

最新評(píng)論