<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          SpringBoot使用@Transactional注解配置事務(wù)

          共 4812字,需瀏覽 10分鐘

           ·

          2020-09-12 20:27

          點(diǎn)擊上方藍(lán)色字體,選擇“標(biāo)星公眾號(hào)”

          優(yōu)質(zhì)文章,第一時(shí)間送達(dá)

          ? 作者?|??宋曉華?

          來(lái)源 |? urlify.cn/2qe6ju

          66套java從入門(mén)到精通實(shí)戰(zhàn)課程分享?

          1、詳細(xì)介紹
          事務(wù)管理是應(yīng)用系統(tǒng)開(kāi)發(fā)中必不可少的一部分。Spring 為事務(wù)管理提供了豐富的功能支持。Spring 事務(wù)管理分為編程式和聲明式的兩種方式。
          編程式事務(wù)指的是通過(guò)編碼方式實(shí)現(xiàn)事務(wù);聲明式事務(wù)基于 AOP,將具體業(yè)務(wù)邏輯與事務(wù)處理解耦。
          聲明式事務(wù)管理使業(yè)務(wù)代碼邏輯不受污染, 因此在實(shí)際使用中聲明式事務(wù)用的比較多。

          聲明式事務(wù)有兩種方式,一種是在配置文件(xml)中做相關(guān)的事務(wù)規(guī)則聲明,另一種是基于@Transactional注解的方式。

          @Transactional可以作用于接口、接口方法、類(lèi)以及類(lèi)方法上。當(dāng)作用于類(lèi)上時(shí),該類(lèi)的所有public方法將都具有該類(lèi)型的事務(wù)屬性,同時(shí),我們也可以在方法級(jí)別使用該標(biāo)注來(lái)覆蓋類(lèi)級(jí)別的定義。

          雖然@Transactional注解可以作用于接口、接口方法、類(lèi)以及類(lèi)方法上,但是Spring建議不要在接口或者接口方法上使用該注解,因?yàn)檫@只有在使用基于接口的代理時(shí)它才會(huì)生效。

          另外,@Transactional注解應(yīng)該只被應(yīng)用到public方法上,這是由Spring AOP的本質(zhì)決定的。如果你在protected、private或者默認(rèn)可見(jiàn)性的方法上使用@Transactional注解,這將被忽略,也不會(huì)拋出任何異常。

          默認(rèn)情況下,只有來(lái)自外部的方法調(diào)用才會(huì)被AOP代理捕獲,也就是,類(lèi)內(nèi)部方法調(diào)用本類(lèi)內(nèi)部的其他方法并不會(huì)引起事務(wù)行為,即使被調(diào)用方法使用@Transactional注解進(jìn)行修飾。

          2、使用方法
          注:SpringBoot項(xiàng)目會(huì)自動(dòng)配置一個(gè)DataSourceTransactionManager,所以我們只需在方法(或者類(lèi))加上@Transactional注解,就自動(dòng)納入Spring的事務(wù)管理了。如下在方法加上 @Transactional 注解:

          拋出異常之后,事務(wù)會(huì)自動(dòng)回滾,數(shù)據(jù)不會(huì)插入到數(shù)據(jù)庫(kù)。

          3、Spring事務(wù)的默認(rèn)回滾機(jī)制
          Spring的事務(wù)管理默認(rèn)是針對(duì)unchecked exception回滾,也就是默認(rèn)對(duì)Error異常和RuntimeException異常以及其子類(lèi)進(jìn)行事務(wù)回滾,且必須拋出異常。若使用try-catch對(duì)其異常捕獲則不會(huì)進(jìn)行回滾?。‥rror異常和RuntimeException異常拋出時(shí)不需要方法調(diào)用throws或try-catch語(yǔ)句)。而checked exception** 則必須用try語(yǔ)句塊進(jìn)行處理或者把異常交給上級(jí)方法處理總之就是必須寫(xiě)代碼處理它,所以必須在service捕獲異常,然后再次拋出,這樣事務(wù)方才起效。

          4、Java 異常介紹
          Java標(biāo)準(zhǔn)庫(kù)內(nèi)建了一些通用的異常,這些類(lèi)以Throwable為頂層父類(lèi)。Throwable又派生出Error類(lèi)和Exception類(lèi)。錯(cuò)誤:Error類(lèi)以及他的子類(lèi)的實(shí)例,代表了JVM本身的錯(cuò)誤。錯(cuò)誤不能被程序員通過(guò)代碼處理,Error很少出現(xiàn)。因此,程序員應(yīng)該關(guān)注Exception為父類(lèi)的分支下的各種異常類(lèi)。異常:Exception以及他的子類(lèi),代表程序運(yùn)行時(shí)發(fā)送的各種不期望發(fā)生的事件??梢员籎ava異常處理機(jī)制使用,是異常處理的核心。

          注意:上圖中有個(gè)錯(cuò)誤 - ClassNotFoundException不屬于運(yùn)行時(shí)異常!總體上我們根據(jù)Javac對(duì)異常的處理要求,將異常類(lèi)分為2類(lèi)。非檢查異常(unckecked exception):Error和RuntimeException以及他們的子類(lèi)。javac在編譯時(shí),不會(huì)提示和發(fā)現(xiàn)這樣的異常,不要求在程序處理這些異常。所以如果愿意,我們可以編寫(xiě)代碼處理(使用try…catch…finally)這樣的異常,也可以不處理。對(duì)于這些異常,我們應(yīng)該修正代碼,而不是去通過(guò)異常處理器處理。這樣的異常發(fā)生的原因多半是代碼寫(xiě)的有問(wèn)題。

          除0錯(cuò)誤ArithmeticException,錯(cuò)誤的強(qiáng)制類(lèi)型轉(zhuǎn)換錯(cuò)誤ClassCastException,數(shù)組索引越界ArrayIndexOutOfBoundsException,使用了空對(duì)象NullPointerException等等。檢查異常(checked exception):除了Error 和 RuntimeException的其它異常。javac強(qiáng)制要求程序員為這樣的異常做預(yù)備處理工作(使用try…catch…finally或者throws)。在方法中要么用try-catch語(yǔ)句捕獲它并處理,要么用throws子句聲明拋出它,否則編譯不會(huì)通過(guò)。這樣的異常一般是由程序的運(yùn)行環(huán)境導(dǎo)致的。因?yàn)槌绦蚩赡鼙贿\(yùn)行在各種未知的環(huán)境下,而程序員無(wú)法干預(yù)用戶(hù)如何使用他編寫(xiě)的程序,于是程序員就應(yīng)該為這樣的異常時(shí)刻準(zhǔn)備著。
          如SQLException , IOException,ClassNotFoundException 等。需要明確的是:檢查和非檢查是對(duì)于javac來(lái)說(shuō)的,這樣就很好理解和區(qū)分了。

          5、@Transactional注解屬性介紹
          value和transactionManager屬性,它們兩個(gè)是一樣的意思。當(dāng)配置了多個(gè)事務(wù)管理器時(shí),可以使用該屬性指定選擇哪個(gè)事務(wù)管理器。
          propagation屬性,事務(wù)的傳播行為,默認(rèn)值為Propagation.REQUIRED。

          可選的值有:
          Propagation.REQUIRED 如果當(dāng)前存在事務(wù),則加入該事務(wù),如果當(dāng)前不存在事務(wù),則創(chuàng)建一個(gè)新的事務(wù)。如a方法和b方法都添加了注解,使用默認(rèn)傳播模式,則a方法內(nèi)部調(diào)用b方法,會(huì)把兩個(gè)方法的事務(wù)合并為一個(gè)事務(wù)。這里又會(huì)存在問(wèn)題,如果b方法內(nèi)部拋了異常,而a方法catch了b方法的異常,那這個(gè)事務(wù)還能正常運(yùn)行嗎?答案是不行!會(huì)拋出異常:
          org.springframework.transaction.UnexpectedRollbackException: Transaction rolled back because it has been marked as rollback-only,因?yàn)楫?dāng)ServiceB中拋出了一個(gè)異常以后,ServiceB會(huì)把當(dāng)前的transaction標(biāo)記為需要rollback。但是ServiceA中捕獲了這個(gè)異常,并進(jìn)行了處理,認(rèn)為當(dāng)前transaction應(yīng)該正常commit。此時(shí)就出現(xiàn)了前后不一致,也就是因?yàn)檫@樣,拋出了前面的UnexpectedRollbackException。Propagation.SUPPORTS
          如果當(dāng)前存在事務(wù),則加入該事務(wù);如果當(dāng)前不存在事務(wù),則以非事務(wù)的方式繼續(xù)運(yùn)行。

          Propagation.MANDATORY 如果當(dāng)前存在事務(wù),則加入該事務(wù);如果當(dāng)前不存在事務(wù),則拋出異常。

          Propagation.REQUIRES_NEW 重新創(chuàng)建一個(gè)新的事務(wù),如果當(dāng)前存在事務(wù),暫停當(dāng)前的事務(wù)。這個(gè)屬性可以實(shí)現(xiàn):
          類(lèi)A中的a方法加上默認(rèn)注解@Transactional(propagation = Propagation.REQUIRED),類(lèi)B中的b方法加上注解@Transactional(propagation = Propagation.REQUIRES_NEW),然后在a方法中調(diào)用b方法操作數(shù)據(jù)庫(kù),再在a方法最后拋出異常,會(huì)發(fā)現(xiàn)a方法中的b方法對(duì)數(shù)據(jù)庫(kù)的操作沒(méi)有回滾,因?yàn)镻ropagation.REQUIRES_NEW會(huì)暫停a方法的事務(wù)。

          Propagation.NOT_SUPPORTED 以非事務(wù)的方式運(yùn)行,如果當(dāng)前存在事務(wù),暫停當(dāng)前的事務(wù)。

          Propagation.NEVER 以非事務(wù)的方式運(yùn)行,如果當(dāng)前存在事務(wù),則拋出異常。

          Propagation.NESTED 和 Propagation.REQUIRED 效果一樣。

          isolation屬性 事務(wù)的隔離級(jí)別,默認(rèn)值為 Isolation.DEFAULT。

          可選的值有:Isolation.DEFAULT 使用底層數(shù)據(jù)庫(kù)默認(rèn)的隔離級(jí)別。Isolation.READ_UNCOMMITTED ,Isolation.READ_COMMITTED ,Isolation.REPEATABLE_READ,Isolation.SERIALIZABLE

          timeout屬性:事務(wù)的超時(shí)時(shí)間,默認(rèn)值為-1。如果超過(guò)該時(shí)間限制但事務(wù)還沒(méi)有完成,則自動(dòng)回滾事務(wù)。

          readOnly屬性:指定事務(wù)是否為只讀事務(wù),默認(rèn)值為 false;為了忽略那些不需要事務(wù)的方法,比如讀取數(shù)據(jù),可以設(shè)置 read-only 為 true。

          rollbackFor屬性:用于指定能夠觸發(fā)事務(wù)回滾的異常類(lèi)型,可以指定多個(gè)異常類(lèi)型。

          noRollbackFor屬性:拋出指定的異常類(lèi)型,不回滾事務(wù),也可以指定多個(gè)異常類(lèi)型。

          6、@Transactional事務(wù)幾點(diǎn)注意,這里面有幾點(diǎn)需要大家留意:
          A. 一個(gè)功能是否要事務(wù),必須納入設(shè)計(jì)、編碼考慮。不能僅僅完成了基本功能就ok。
          B. 如果加了事務(wù),必須做好開(kāi)發(fā)環(huán)境測(cè)試(測(cè)試環(huán)境也盡量觸發(fā)異常、測(cè)試回滾),確保事務(wù)生效。
          C. 以下列了事務(wù)使用過(guò)程的注意事項(xiàng),請(qǐng)大家留意。
          1.不要在接口上聲明@Transactional,而要在具體類(lèi)的方法上使用@Transactional注解,否則注解可能無(wú)效。


          2.不要圖省事,將@Transactional放置在類(lèi)級(jí)的聲明中,放在類(lèi)聲明,會(huì)使得所有方法都有事務(wù)。故@Transactional應(yīng)該放在方法級(jí)別,不需要使用事務(wù)的方法,就不要放置事務(wù),比如查詢(xún)方法。否則對(duì)性能是有影響的。


          3.使用了@Transactional的方法,對(duì)同一個(gè)類(lèi)里面的方法調(diào)用,@Transactional無(wú)效。比如有一個(gè)類(lèi)Test,它的一個(gè)方法A,A再調(diào)用Test本類(lèi)的方法B(不管B是否public還是private),但A沒(méi)有聲明注解事務(wù),而B(niǎo)有。則外部調(diào)用A之后,B的事務(wù)是不會(huì)起作用的。(經(jīng)常在這里出錯(cuò))


          4.使用了@Transactional的方法,只能是public,@Transactional注解的方法都是被外部其他類(lèi)調(diào)用才有效,故只能是public。道理和上面的有關(guān)聯(lián)。故在protected、private或者package-visible的方法上使用 @Transactional 注解,它也不會(huì)報(bào)錯(cuò),但事務(wù)無(wú)效。


          5.spring的事務(wù)在拋異常的時(shí)候會(huì)回滾,如果是catch捕獲了,事務(wù)無(wú)效??梢栽赾atch里面加throw new RuntimeException();


          6.最后有個(gè)關(guān)鍵的一點(diǎn):和鎖同時(shí)使用需要注意:由于Spring事務(wù)是通過(guò)AOP實(shí)現(xiàn)的,所以在方法執(zhí)行之前會(huì)有開(kāi)啟事務(wù),之后會(huì)有提交事務(wù)邏輯。而synchronized代碼塊執(zhí)行是在事務(wù)之內(nèi)執(zhí)行的,可以推斷在synchronized代碼塊執(zhí)行完時(shí),事務(wù)還未提交,其他線程進(jìn)入synchronized代碼塊后,讀取的數(shù)據(jù)不是最新的。


          所以必須使synchronized鎖的范圍大于事務(wù)控制的范圍,把synchronized加到Controller層或者大于事務(wù)邊界的調(diào)用層!



          粉絲福利:108本java從入門(mén)到大神精選電子書(shū)領(lǐng)取

          ???

          ?長(zhǎng)按上方鋒哥微信二維碼?2 秒
          備注「1234」即可獲取資料以及
          可以進(jìn)入java1234官方微信群



          感謝點(diǎn)贊支持下哈?


          瀏覽 45
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  成人免费性生活视频 | 天天插综合 | 影音先锋成人资源在线 | 囯产精品无码成人久久久 | 秋霞乱伦 |