<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>

          @Transactional屬性詳解

          共 11914字,需瀏覽 24分鐘

           ·

          2021-05-25 21:09

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

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

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

          聲明式事務(wù)管理建立在AOP之上的。其本質(zhì)是對方法前后進(jìn)行攔截,然后在目標(biāo)方法開始之前創(chuàng)建或者加入一個(gè)事務(wù),在執(zhí)行完目標(biāo)方法之后根據(jù)執(zhí)行情況提交或者回滾事務(wù)。

          簡而言之,@Transactional注解在代碼執(zhí)行出錯(cuò)的時(shí)候能夠進(jìn)行事務(wù)的回滾。

          使用說明

          1. 需要在啟動(dòng)類上添加@EnableTransactionManagement注解。

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

          3. 在項(xiàng)目中,@Transactional(rollbackFor=Exception.class),如果類加了這個(gè)注解,那么這個(gè)類里面的方法拋出異常,就會(huì)回滾,數(shù)據(jù)庫里面的數(shù)據(jù)也會(huì)回滾。

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

          而至于什么是運(yùn)行時(shí)異常(RuntimeException),什么是非運(yùn)行時(shí)異常,可通過下圖所示理解(圖片截取網(wǎng)絡(luò))

          注解失效問題

          正常情況下,只要在方法上添加@Transactional注解就完事了,但是需要注意的是,雖然使用簡單,但是如果不合理地使用注解,還是會(huì)存在注解失效的問題。(以下部分參考了兩位大佬的文章https://baijiahao.baidu.com/s?id=1661650900351466294&wfr=spider&for=pc,
          http://www.voidcn.com/article/p-eplwrich-brp.html)

          @Transactional 應(yīng)用在非 public 修飾的方法上

          事務(wù)攔截器在目標(biāo)方法執(zhí)行前后進(jìn)行攔截,內(nèi)部會(huì)調(diào)用方法來獲取Transactional 注解的事務(wù)配置信息,調(diào)用前會(huì)檢查目標(biāo)方法的修飾符是否為 public,不是 public則不會(huì)獲取@Transactional 的屬性配置信息。

          @Transactional 注解屬性 rollbackFor 設(shè)置錯(cuò)誤

          rollbackFor 可以指定能夠觸發(fā)事務(wù)回滾的異常類型。Spring默認(rèn)拋出了未檢查unchecked異常(繼承自 RuntimeException 的異常)或者 Error才回滾事務(wù);其他異常不會(huì)觸發(fā)回滾事務(wù)。如果在事務(wù)中拋出其他類型的異常,但卻期望 Spring 能夠回滾事務(wù),就需要指定rollbackFor屬性。

          同一個(gè)類中方法調(diào)用,導(dǎo)致@Transactional失效

          開發(fā)中避免不了會(huì)對同一個(gè)類里面的方法調(diào)用,比如有一個(gè)類Test,它的一個(gè)方法A,A再調(diào)用本類的方法B(不論方法B是用public還是private修飾),但方法A沒有聲明注解事務(wù),而B方法有。則外部調(diào)用方法A之后,方法B的事務(wù)是不會(huì)起作用的。這也是經(jīng)常犯錯(cuò)誤的一個(gè)地方。
          那為啥會(huì)出現(xiàn)這種情況?其實(shí)這還是由于使用Spring AOP代理造成的,因?yàn)橹挥挟?dāng)事務(wù)方法被當(dāng)前類以外的代碼調(diào)用時(shí),才會(huì)由Spring生成的代理對象來管理。

          異常被你的 catch“吃了”導(dǎo)致@Transactional失效

          如果你手動(dòng)的catch捕獲這個(gè)異常并進(jìn)行處理,事務(wù)管理器會(huì)認(rèn)為當(dāng)前事務(wù)應(yīng)該正常commit,就會(huì)導(dǎo)致注解失效,如果非要捕獲且不失效,就必須在代碼塊內(nèi)throw new Exception拋出異常。

          數(shù)據(jù)庫引擎不支持事務(wù)

          開啟事務(wù)的前提就是需要數(shù)據(jù)庫的支持,我們一般使用的Mysql引擎時(shí)支持事務(wù)的,所以一般不會(huì)出現(xiàn)這種問題。

          開啟多線程任務(wù)時(shí),事務(wù)管理會(huì)受到影響

          因?yàn)榫€程不屬于spring托管,故線程不能夠默認(rèn)使用spring的事務(wù),也不能獲取spring注入的bean在被spring聲明式事務(wù)管理的方法內(nèi)開啟多線程,多線程內(nèi)的方法不被事務(wù)控制。
          如下代碼,線程內(nèi)調(diào)用insert方法,spring不會(huì)把insert方法加入事務(wù)就算在insert方法上加入@Transactional注解,也不起作用。

          @Service  
          public class ServiceA {  
             
              @Transactional  
              public void threadMethod(){  
                  this.insert();  
                   System.out.println("main insert is over");  
                  for(int a=0 ;a<3;a++){  
                      ThreadOperation threadOperation= new ThreadOperation();  
                      Thread innerThread = new Thread(threadOperation);  
                      innerThread.start();  
                  }  
              }  
             
              public  class ThreadOperation implements Runnable {  
                  public ThreadOperation(){  
                  }  
                  @Override  
                  public void run(){  
                      insert();  
                      System.out.println("thread insert is over");  
                  }  
              }  
             
              public void insert(){  
             
              //do insert......  
             
              }  
          }  

          如果把上面insert方法提出到新的類中,加入事務(wù)注解,就能成功的把insert方法加入到事務(wù)管理當(dāng)中

          @Service  
          public class ServiceA {  
             
          @Autowired  
          private ServiceB serviceB;  
             
              @Transactional  
              public void threadMethod(){  
                  this.insert();  
                  System.out.println("main insert is over");  
                  for(int a=0 ;a<3;a++){  
                      ThreadOperation threadOperation= new ThreadOperation();  
                      Thread innerThread = new Thread(threadOperation);  
                      innerThread.start();  
                  }  
              }  
             
              public  class ThreadOperation implements Runnable {  
                  public ThreadOperation(){  
                  }  
                  @Override  
                  public void run(){  
                      serviceB.insert();  
                      System.out.println("thread insert is over");  
                  }  
              }  
             
              public void insert(){  
             
                  //do insert......  
             
              }  
          }  
             
          @Service  
          public class ServiceB {  
             
              @Transactional  
              public void insert(){  
             
                  //do insert......  
             
              }  
             
          }  

          另外,使用多線程事務(wù)的情況下,進(jìn)行回滾,比較麻煩。thread的run方法,有個(gè)特別之處,它不會(huì)拋出異常,但異常會(huì)導(dǎo)致線程終止運(yùn)行。
          最麻煩的是,在線程中拋出的異常即使在主線程中使用try…catch也無法截獲這非常糟糕,我們必須要“感知”到異常的發(fā)生。比如某個(gè)線程在處理重要的事務(wù),當(dāng)thread異常終止,我必須要收到異常的報(bào)告,才能回滾事務(wù)。這時(shí)可以使用線程的UncaughtExceptionHandler進(jìn)行異常處理,UncaughtExceptionHandler名字意味著處理未捕獲的異常。更明確的說,它處理未捕獲的運(yùn)行時(shí)異常。
          如下代碼
          線程出要使用
          ①處要拋出異常
          ②處要捕捉異常,并且要拋出RuntimeException
          ③處手動(dòng)處理回滾邏輯

          @Service  
          public class ServiceA {  
             
          @Autowired  
          private ServiceB serviceB;  
             
              @Transactional  
              public void threadMethod(){  
                  this.insert();  
                  System.out.println("main insert is over");  
                  for(int a=0 ;a<3;a++){  
                      ThreadOperation threadOperation= new ThreadOperation();  
                      Thread innerThread = new Thread(threadOperation);  
                      innerThread.setUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {  
                         public void uncaughtException(Thread t, Throwable e) {  
                             try {  
                                  serviceB.delete();③  
                             } catch (Exception e1) {  
                                 e1.printStackTrace();  
                             }  
                         }  
                      });  
                      innerThread.start();  
                  }  
              }  
             
              public  class ThreadOperation implements Runnable {  
                  public ThreadOperation(){  
                  }  
                  @Override  
                  public void run(){  
                      try {  
                         serviceB.insert();  
                     }catch (Exception ex){ ②  
                      System.out.println(" Exception in run ");  
                         throw new RuntimeException();  
                     }  
                      System.out.println("thread insert is over");  
                  }  
              }  
             
              public void insert(){  
             
                  //do insert......  
             
              }  
          }  
             
          @Service  
          public class ServiceB {  
             
              @Transactional  
              public void insert() throws Exception{ ①  
             
              //do insert......  
             
              }  
             
              @Transactional  
              public void delete() throws Exception{   
             
                  //do delete......  
             
              }  
             
          }  
          ————————————————
          版權(quán)聲明:本文為CSDN博主「丶煒欽」的原創(chuàng)文章,遵循CC 4.0 BY-SA版權(quán)協(xié)議,轉(zhuǎn)載請附上原文出處鏈接及本聲明。
          原文鏈接:https://blog.csdn.net/weixin_44521690/article/details/116797363



          版權(quán)聲明:本文為博主原創(chuàng)文章,遵循 CC 4.0 BY-SA 版權(quán)協(xié)議,轉(zhuǎn)載請附上原文出處鏈接和本聲明。

          本文鏈接:

          https://blog.csdn.net/weixin_44521690/article/details/116797363






          粉絲福利:Java從入門到入土學(xué)習(xí)路線圖

          ??????

          ??長按上方微信二維碼 2 秒


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

          瀏覽 128
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

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

          手機(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>
                  在线免费观看ww视频 | 成人大片在线播放 | 亚洲青草在线 | 三级无码在线 | 五月午夜激情 |