欧美亚洲自拍偷拍_日本一区视频在线观看_国产二区在线播放_亚洲男人第一天堂

二維碼
企資網(wǎng)

掃一掃關注

當前位置: 首頁 » 企資快訊 » 匯總 » 正文

Spring事務傳播講解透徹的深度好文

放大字體  縮小字體 發(fā)布日期:2021-08-22 01:03:23    作者:史舒文    瀏覽次數(shù):52
導讀

事務傳播七種事務傳播行為詳解與示例在介紹七種事務傳播行為前,我們先設計一個場景,幫助大家理解,場景描述如下現(xiàn)有兩個方法A和B,方法A執(zhí)行會在數(shù)據(jù)庫ATable插入一條數(shù)據(jù),方法B執(zhí)行會在數(shù)據(jù)庫BTable插入一條數(shù)據(jù)

事務傳播

七種事務傳播行為詳解與示例

在介紹七種事務傳播行為前,我們先設計一個場景,幫助大家理解,場景描述如下

現(xiàn)有兩個方法A和B,方法A執(zhí)行會在數(shù)據(jù)庫ATable插入一條數(shù)據(jù),方法B執(zhí)行會在數(shù)據(jù)庫BTable插入一條數(shù)據(jù),偽代碼如下:

//將傳入?yún)?shù)a存入ATablepubilc void A(a){    insertIntoATable(a);    }//將傳入?yún)?shù)b存入BTablepublic void B(b){    insertIntoBTable(b);}

接下來,我們看看在如下場景下,沒有事務,情況會怎樣

public void testMain(){    A(a1);  //調(diào)用A入?yún)1    testB();    //調(diào)用testB}public void testB(){    B(b1);  //調(diào)用B入?yún)1    throw Exception;     //發(fā)生異常拋出    B(b2);  //調(diào)用B入?yún)2}

在這里要做一個重要提示:Spring中事務的默認實現(xiàn)使用的是AOP,也就是代理的方式,如果大家在使用代碼測試時,同一個Service類中的方法相互調(diào)用需要使用注入的對象來調(diào)用,不要直接使用this.方法名來調(diào)用,this.方法名調(diào)用是對象內(nèi)部方法調(diào)用,不會通過Spring代理,也就是事務不會起作用

以上偽代碼描述的一個場景,方法testMain和testB都沒有事務,執(zhí)行testMain方法,那么結果會怎么樣呢?

相信大家都知道了,就是a1數(shù)據(jù)成功存入ATable表,b1數(shù)據(jù)成功存入BTable表,而在拋出異常后b2數(shù)據(jù)存儲就不會執(zhí)行,也就是b2數(shù)據(jù)不會存入數(shù)據(jù)庫,這就是沒有事務的場景。

接下我們就開始理解七種不同事務傳播類型的含義

REQUIRED(Spring默認的事務傳播類型)

如果當前沒有事務,則自己新建一個事務,如果當前存在事務,則加入這個事務

源碼說明如下:

    REQUIRED(TransactionDefinition.PROPAGATION_REQUIRED),

(示例1)根據(jù)場景舉栗子,我們在testMain和testB上聲明事務,設置傳播行為REQUIRED,偽代碼如下:

@Transactional(propagation = Propagation.REQUIRED)public void testMain(){    A(a1);  //調(diào)用A入?yún)1    testB();    //調(diào)用testB}@Transactional(propagation = Propagation.REQUIRED)public void testB(){    B(b1);  //調(diào)用B入?yún)1    throw Exception;     //發(fā)生異常拋出    B(b2);  //調(diào)用B入?yún)2}

該場景下執(zhí)行testMain方法結果如何呢?

數(shù)據(jù)庫沒有插入新的數(shù)據(jù),數(shù)據(jù)庫還是保持著執(zhí)行testMain方法之前的狀態(tài),沒有發(fā)生改變。testMain上聲明了事務,在執(zhí)行testB方法時就加入了testMain的事務(當前存在事務,則加入這個事務),在執(zhí)行testB方法拋出異常后事務會發(fā)生回滾,又testMain和testB使用的同一個事務,所以事務回滾后testMain和testB中的操作都會回滾,也就使得數(shù)據(jù)庫仍然保持初始狀態(tài)

(示例2)根據(jù)場景再舉一個栗子,我們只在testB上聲明事務,設置傳播行為REQUIRED,偽代碼如下:

public void testMain(){    A(a1);  //調(diào)用A入?yún)1    testB();    //調(diào)用testB}@Transactional(propagation = Propagation.REQUIRED)public void testB(){    B(b1);  //調(diào)用B入?yún)1    throw Exception;     //發(fā)生異常拋出    B(b2);  //調(diào)用B入?yún)2}

這時的執(zhí)行結果又如何呢?

數(shù)據(jù)a1存儲成功,數(shù)據(jù)b1和b2沒有存儲。由于testMain沒有聲明事務,testB有聲明事務且傳播行為是REQUIRED,所以在執(zhí)行testB時會自己新建一個事務(如果當前沒有事務,則自己新建一個事務),testB拋出異常則只有testB中的操作發(fā)生了回滾,也就是b1的存儲會發(fā)生回滾,但a1數(shù)據(jù)不會回滾,所以最終a1數(shù)據(jù)存儲成功,b1和b2數(shù)據(jù)沒有存儲

SUPPORTS

當前存在事務,則加入當前事務,如果當前沒有事務,就以非事務方法執(zhí)行

源碼注釋如下(太長省略了一部分),其中里面有一個提醒翻譯一下就是:“對于具有事務同步的事務管理器,SUPPORTS與完全沒有事務稍有不同,因為她定義了可能應用同步的事務范圍”。這個是與事務同步管理器相關的一個注意項,這里不過多討論。

    SUPPORTS(TransactionDefinition.PROPAGATION_SUPPORTS),

(示例3)根據(jù)場景舉栗子,我們只在testB上聲明事務,設置傳播行為SUPPORTS,偽代碼如下:

public void testMain(){    A(a1);  //調(diào)用A入?yún)1    testB();    //調(diào)用testB}@Transactional(propagation = Propagation.SUPPORTS)public void testB(){    B(b1);  //調(diào)用B入?yún)1    throw Exception;     //發(fā)生異常拋出    B(b2);  //調(diào)用B入?yún)2}

這種情況下,執(zhí)行testMain的最終結果就是,a1,b1存入數(shù)據(jù)庫,b2沒有存入數(shù)據(jù)庫。由于testMain沒有聲明事務,且testB的事務傳播行為是SUPPORTS,所以執(zhí)行testB時就是沒有事務的(如果當前沒有事務,就以非事務方法執(zhí)行),則在testB拋出異常時也不會發(fā)生回滾,所以最終結果就是a1和b1存儲成功,b2沒有存儲。

那么當我們在testMain上聲明事務且使用REQUIRED傳播方式的時候,這個時候執(zhí)行testB就滿足當前存在事務,則加入當前事務,在testB拋出異常時事務就會回滾,最終結果就是a1,b1和b2都不會存儲到數(shù)據(jù)庫

MANDATORY

當前存在事務,則加入當前事務,如果當前事務不存在,則拋出異常。

源碼注釋如下:

    MANDATORY(TransactionDefinition.PROPAGATION_MANDATORY),

(示例4)場景舉栗子,我們只在testB上聲明事務,設置傳播行為MANDATORY,偽代碼如下:

public void testMain(){    A(a1);  //調(diào)用A入?yún)1    testB();    //調(diào)用testB}@Transactional(propagation = Propagation.MANDATORY)public void testB(){    B(b1);  //調(diào)用B入?yún)1    throw Exception;     //發(fā)生異常拋出    B(b2);  //調(diào)用B入?yún)2}

這種情形的執(zhí)行結果就是a1存儲成功,而b1和b2沒有存儲。b1和b2沒有存儲,并不是事務回滾的原因,而是因為testMain方法沒有聲明事務,在去執(zhí)行testB方法時就直接拋出事務要求的異常(如果當前事務不存在,則拋出異常),所以testB方法里的內(nèi)容就沒有執(zhí)行。

那么如果在testMain方法進行事務聲明,并且設置為REQUIRED,則執(zhí)行testB時就會使用testMain已經(jīng)開啟的事務,遇到異常就正常的回滾了。

REQUIRES_NEW

創(chuàng)建一個新事務,如果存在當前事務,則掛起該事務。

可以理解為設置事務傳播類型為REQUIRES_NEW的方法,在執(zhí)行時,不論當前是否存在事務,總是會新建一個事務。

源碼注釋如下

    REQUIRES_NEW(TransactionDefinition.PROPAGATION_REQUIRES_NEW),

(示例5)場景舉栗子,為了說明設置REQUIRES_NEW的方法會開啟新事務,我們把異常發(fā)生的位置換到了testMain,然后給testMain聲明事務,傳播類型設置為REQUIRED,testB也聲明事務,設置傳播類型為REQUIRES_NEW,偽代碼如下

@Transactional(propagation = Propagation.REQUIRED)public void testMain(){    A(a1);  //調(diào)用A入?yún)1    testB();    //調(diào)用testB    throw Exception;     //發(fā)生異常拋出}@Transactional(propagation = Propagation.REQUIRES_NEW)public void testB(){    B(b1);  //調(diào)用B入?yún)1    B(b2);  //調(diào)用B入?yún)2}

這種情形的執(zhí)行結果就是a1沒有存儲,而b1和b2存儲成功,因為testB的事務傳播設置為REQUIRES_NEW,所以在執(zhí)行testB時會開啟一個新的事務,testMain中發(fā)生的異常時在testMain所開啟的事務中,所以這個異常不會影響testB的事務提交,testMain中的事務會發(fā)生回滾,所以最終a1就沒有存儲,而b1和b2就存儲成功了。

與這個場景對比的一個場景就是testMain和testB都設置為REQUIRED,那么上面的代碼執(zhí)行結果就是所有數(shù)據(jù)都不會存儲,因為testMain和testMain是在同一個事務下的,所以事務發(fā)生回滾時,所有的數(shù)據(jù)都會回滾

NOT_SUPPORTED

始終以非事務方式執(zhí)行,如果當前存在事務,則掛起當前事務

可以理解為設置事務傳播類型為NOT_SUPPORTED的方法,在執(zhí)行時,不論當前是否存在事務,都會以非事務的方式運行。

源碼說明如下

    NOT_SUPPORTED(TransactionDefinition.PROPAGATION_NOT_SUPPORTED),

(示例6)場景舉栗子,testMain傳播類型設置為REQUIRED,testB傳播類型設置為NOT_SUPPORTED,且異常拋出位置在testB中,偽代碼如下

@Transactional(propagation = Propagation.REQUIRED)public void testMain(){    A(a1);  //調(diào)用A入?yún)1    testB();    //調(diào)用testB}@Transactional(propagation = Propagation.NOT_SUPPORTED)public void testB(){    B(b1);  //調(diào)用B入?yún)1    throw Exception;     //發(fā)生異常拋出    B(b2);  //調(diào)用B入?yún)2}

該場景的執(zhí)行結果就是a1和b2沒有存儲,而b1存儲成功。testMain有事務,而testB不使用事務,所以執(zhí)行中testB的存儲b1成功,然后拋出異常,此時testMain檢測到異常事務發(fā)生回滾,但是由于testB不在事務中,所以只有testMain的存儲a1發(fā)生了回滾,最終只有b1存儲成功,而a1和b1都沒有存儲

NEVER

不使用事務,如果當前事務存在,則拋出異常

很容易理解,就是我這個方法不使用事務,并且調(diào)用我的方法也不允許有事務,如果調(diào)用我的方法有事務則我直接拋出異常。

源碼注釋如下:

    NEVER(TransactionDefinition.PROPAGATION_NEVER),

(示例7)場景舉栗子,testMain設置傳播類型為REQUIRED,testB傳播類型設置為NEVER,并且把testB中的拋出異常代碼去掉,則偽代碼如下

@Transactional(propagation = Propagation.REQUIRED)public void testMain(){    A(a1);  //調(diào)用A入?yún)1    testB();    //調(diào)用testB}@Transactional(propagation = Propagation.NEVER)public void testB(){    B(b1);  //調(diào)用B入?yún)1    B(b2);  //調(diào)用B入?yún)2}

該場景執(zhí)行,直接拋出事務異常,且不會有數(shù)據(jù)存儲到數(shù)據(jù)庫。由于testMain事務傳播類型為REQUIRED,所以testMain是運行在事務中,而testB事務傳播類型為NEVER,所以testB不會執(zhí)行而是直接拋出事務異常,此時testMain檢測到異常就發(fā)生了回滾,所以最終數(shù)據(jù)庫不會有數(shù)據(jù)存入。

NESTED

如果當前事務存在,則在嵌套事務中執(zhí)行,否則REQUIRED的操作一樣(開啟一個事務)

這里需要注意兩點:

  • 和REQUIRES_NEW的區(qū)別

    REQUIRES_NEW是新建一個事務并且新開啟的這個事務與原有事務無關,而NESTED則是當前存在事務時(我們把當前事務稱之為父事務)會開啟一個嵌套事務(稱之為一個子事務)。
    在NESTED情況下父事務回滾時,子事務也會回滾,而在REQUIRES_NEW情況下,原有事務回滾,不會影響新開啟的事務。

  • 和REQUIRED的區(qū)別

    REQUIRED情況下,調(diào)用方存在事務時,則被調(diào)用方和調(diào)用方使用同一事務,那么被調(diào)用方出現(xiàn)異常時,由于共用一個事務,所以無論調(diào)用方是否catch其異常,事務都會回滾
    而在NESTED情況下,被調(diào)用方發(fā)生異常時,調(diào)用方可以catch其異常,這樣只有子事務回滾,父事務不受影響

    (示例8)場景舉栗子,testMain設置為REQUIRED,testB設置為NESTED,且異常發(fā)生在testMain中,偽代碼如下

    @Transactional(propagation = Propagation.REQUIRED)public void testMain(){    A(a1);  //調(diào)用A入?yún)1    testB();    //調(diào)用testB    throw Exception;     //發(fā)生異常拋出}@Transactional(propagation = Propagation.NESTED)public void testB(){    B(b1);  //調(diào)用B入?yún)1    B(b2);  //調(diào)用B入?yún)2}

    該場景下,所有數(shù)據(jù)都不會存入數(shù)據(jù)庫,因為在testMain發(fā)生異常時,父事務回滾則子事務也跟著回滾了,可以與(示例5)比較看一下,就找出了與REQUIRES_NEW的不同

    (示例9)場景舉栗子,testMain設置為REQUIRED,testB設置為NESTED,且異常發(fā)生在testB中,偽代碼如下

    @Transactional(propagation = Propagation.REQUIRED)public void testMain(){    A(a1);  //調(diào)用A入?yún)1    try{        testB();    //調(diào)用testB    }catch(Exception e){    }    A(a2);}@Transactional(propagation = Propagation.NESTED)public void testB(){    B(b1);  //調(diào)用B入?yún)1    throw Exception;     //發(fā)生異常拋出    B(b2);  //調(diào)用B入?yún)2}

    這種場景下,結果是a1,a2存儲成功,b1和b2存儲失敗,因為調(diào)用方catch了被調(diào)方的異常,所以只有子事務回滾了。

    同樣的代碼,如果我們把testB的傳播類型改為REQUIRED,結果也就變成了:沒有數(shù)據(jù)存儲成功。就算在調(diào)用方catch了異常,整個事務還是會回滾,因為,調(diào)用方和被調(diào)方共用的同一個事務

    轉(zhuǎn)自于:https://zhuanlan.zhihu.com/p/148504094

  •  
    (文/史舒文)
    免責聲明
    本文僅代表作發(fā)布者:史舒文個人觀點,本站未對其內(nèi)容進行核實,請讀者僅做參考,如若文中涉及有違公德、觸犯法律的內(nèi)容,一經(jīng)發(fā)現(xiàn),立即刪除,需自行承擔相應責任。涉及到版權或其他問題,請及時聯(lián)系我們刪除處理郵件:weilaitui@qq.com。
     

    Copyright ? 2016 - 2025 - 企資網(wǎng) 48903.COM All Rights Reserved 粵公網(wǎng)安備 44030702000589號

    粵ICP備16078936號

    微信

    關注
    微信

    微信二維碼

    WAP二維碼

    客服

    聯(lián)系
    客服

    聯(lián)系客服:

    在線QQ: 303377504

    客服電話: 020-82301567

    E_mail郵箱: weilaitui@qq.com

    微信公眾號: weishitui

    客服001 客服002 客服003

    工作時間:

    周一至周五: 09:00 - 18:00

    反饋

    用戶
    反饋

    欧美亚洲自拍偷拍_日本一区视频在线观看_国产二区在线播放_亚洲男人第一天堂

          9000px;">

                国产精品久久久久永久免费观看| av网站免费线看精品| 国产一区二区在线电影| 91精品国产乱码久久蜜臀| 成人精品视频一区二区三区| 免费的成人av| 欧美变态tickling挠脚心| av电影在线观看一区| 成熟亚洲日本毛茸茸凸凹| 亚洲精品免费电影| 亚洲免费观看高清完整版在线观看| 国产日韩影视精品| 一本到一区二区三区| 亚洲人亚洲人成电影网站色| 激情图区综合网| 精品无人码麻豆乱码1区2区| 欧美日韩精品免费观看视频 | 国产乱色国产精品免费视频| 91丝袜美腿高跟国产极品老师| heyzo一本久久综合| 大美女一区二区三区| 国产成人综合网| 一区二区三区在线视频观看| 国产不卡在线播放| 亚洲精品视频观看| 首页国产欧美日韩丝袜| 丝袜美腿亚洲色图| 精品少妇一区二区三区视频免付费| 国产制服丝袜一区| 亚洲天堂网中文字| 精品国产一区二区三区四区四| 久久久不卡影院| 中文字幕在线视频一区| 久久影视一区二区| 久久久精品一品道一区| 欧美精品一区男女天堂| 久久久99久久| 国产精品传媒入口麻豆| 亚洲欧美中日韩| 亚洲午夜电影在线| 亚洲精品视频一区二区| 偷拍自拍另类欧美| 国产剧情av麻豆香蕉精品| 99re这里只有精品6| 在线成人av影院| 911精品产国品一二三产区| 欧美mv和日韩mv的网站| 午夜欧美大尺度福利影院在线看| 亚洲国产精品久久人人爱蜜臀| 日本成人在线网站| 国产乱子伦一区二区三区国色天香 | 欧美妇女性影城| 日韩亚洲欧美高清| 久久精品免视看| 亚洲日本青草视频在线怡红院| 亚洲综合免费观看高清完整版 | 国产东北露脸精品视频| aa级大片欧美| 欧美精品18+| 久久久久99精品一区| 亚洲三级电影全部在线观看高清| 亚洲成人动漫av| 韩国精品在线观看| 91在线你懂得| 日韩一级二级三级| 国产精品成人免费精品自在线观看| 一区二区三区丝袜| 精品亚洲成a人| 91麻豆精东视频| 日韩一区二区精品在线观看| 欧美国产在线观看| 天天爽夜夜爽夜夜爽精品视频| 国产做a爰片久久毛片| 91久久线看在观草草青青| 日韩欧美电影在线| 亚洲三级久久久| 激情久久久久久久久久久久久久久久| av网站一区二区三区| 日韩亚洲欧美在线观看| 亚洲色图一区二区| 99这里只有久久精品视频| 国产成人精品免费网站| 欧美日韩一区二区三区四区| 久久影视一区二区| 色综合天天性综合| 国产日产欧产精品推荐色| 国产精品电影一区二区| 91久久奴性调教| 亚洲a一区二区| 亚洲麻豆国产自偷在线| 欧美亚洲禁片免费| 91性感美女视频| 国产在线播放一区| 天天色图综合网| 亚洲高清一区二区三区| 综合电影一区二区三区| 欧美一级久久久久久久大片| 久久影音资源网| 免费高清在线视频一区·| 欧美国产精品一区二区| 日韩欧美的一区二区| 强制捆绑调教一区二区| 亚洲狠狠爱一区二区三区| 日韩激情av在线| 99久久国产综合精品色伊| 欧美日韩夫妻久久| 国产欧美日韩亚州综合 | 日韩一本二本av| 亚洲综合色噜噜狠狠| 成人综合在线视频| 日韩欧美高清dvd碟片| 亚洲欧美区自拍先锋| 国产成人综合网| 久久久久久一二三区| 黄页网站大全一区二区| 777久久久精品| 亚洲成va人在线观看| 色婷婷综合久久久| 国产精品传媒视频| 成人一级片在线观看| 久久色在线视频| 精一区二区三区| 日韩一区二区三区在线视频| 日韩电影一二三区| 欧美日韩三级一区| 亚洲午夜电影在线观看| 日本乱人伦一区| 亚洲女人小视频在线观看| 97久久超碰国产精品| 亚洲欧美区自拍先锋| 色八戒一区二区三区| 日韩美女视频一区| 色综合久久88色综合天天| 亚洲精品精品亚洲| 色av一区二区| 亚洲成av人片观看| 制服丝袜亚洲色图| 美女mm1313爽爽久久久蜜臀| 91精品国产91综合久久蜜臀| 美女脱光内衣内裤视频久久网站 | 99精品久久久久久| 亚洲品质自拍视频| 色呦呦日韩精品| 亚洲国产精品久久不卡毛片 | 99久久99久久综合| 亚洲人成精品久久久久久| 欧美亚洲高清一区| 五月天婷婷综合| 欧美一区二区三区公司| 麻豆极品一区二区三区| 精品福利一区二区三区| 国产精品一区二区x88av| 欧美国产日本韩| 91丝袜美腿高跟国产极品老师| 伊人一区二区三区| 欧美日韩高清一区二区三区| 男人的天堂久久精品| 久久综合给合久久狠狠狠97色69| 国产精品影视在线| 最新日韩av在线| 欧美日韩精品一区二区三区 | 亚洲精品国产无套在线观| 欧美在线免费视屏| 国产精品一区二区三区99| 亚洲人成人一区二区在线观看| 色94色欧美sute亚洲13| 日本欧美一区二区在线观看| 久久久久久久久久久久久夜| av高清久久久| 天堂一区二区在线| 久久久久久久久久久99999| 99视频超级精品| 午夜久久久久久久久久一区二区| 欧美va亚洲va| 91丝袜高跟美女视频| 蜜臀av一区二区在线观看| 国产精品嫩草影院com| 欧美日韩一区二区电影| 韩国av一区二区三区四区| 日韩一区中文字幕| 在线不卡中文字幕播放| 成人av在线电影| 日韩高清不卡一区二区三区| 国产日韩欧美a| 欧美日韩免费高清一区色橹橹| 狠狠色丁香久久婷婷综合丁香| 亚洲欧洲av一区二区三区久久| 欧美二区在线观看| 成人激情图片网| 天堂久久一区二区三区| 欧美激情综合五月色丁香| 欧美视频中文一区二区三区在线观看| 久久99久久精品| 亚洲乱码国产乱码精品精98午夜 | 综合色天天鬼久久鬼色| 欧美一区二区视频在线观看2020| 丰满少妇在线播放bd日韩电影| 亚洲电影一区二区| 国产精品嫩草影院av蜜臀| 日韩视频国产视频|