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

詳解Spring中的Transactional屬性

 更新時間:2021年05月20日 16:16:52   作者:丶煒欽  
今天我在寫代碼的時候,看到了一個注解@Transactional(rollbackFor = Exception.class),今天就和大家分享一下,這個注解的用法,,需要的朋友可以參考下

一、Transactional

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

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

在這里插入圖片描述

二、使用說明

在這里插入圖片描述

  • 在啟動類上添加@EnableTransactionManagement注解。
  • 用于類上時,該類的所有 public 方法將都具有該類型的事務(wù)屬性,同時,我們也可以在方法級別使用該標(biāo)注來覆蓋類級別的定義。
  • 在項目中,@Transactional(rollbackFor=Exception.class),如果類加了這個注解,那么這個類里面的方法拋出異常,就會回滾,數(shù)據(jù)庫里面的數(shù)據(jù)也會回滾。
  • 在@Transactional注解中如果不配置rollbackFor屬性,那么事物只會在遇到RuntimeException的時候才會回滾,加上rollbackFor=Exception.class,可以讓事物在遇到非運行時異常時也回滾。

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

在這里插入圖片描述

三、注解失效問題

正常情況下,只要在方法上添加@Transactional注解就完事了,但是需要注意的是,雖然使用簡單,但是如果不合理地使用注解,還是會存在注解失效的問題。

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

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

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

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

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

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

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

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

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

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

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

因為線程不屬于spring托管,故線程不能夠默認(rèn)使用spring的事務(wù),也不能獲取spring注入的bean在被spring聲明式事務(wù)管理的方法內(nèi)開啟多線程,多線程內(nèi)的方法不被事務(wù)控制。
如下代碼,線程內(nèi)調(diào)用insert方法,spring不會把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方法,有個特別之處,它不會拋出異常,但異常會導(dǎo)致線程終止運行。

最麻煩的是,在線程中拋出的異常即使在主線程中使用try…catch也無法截獲這非常糟糕,我們必須要“感知”到異常的發(fā)生。比如某個線程在處理重要的事務(wù),當(dāng)thread異常終止,我必須要收到異常的報告,才能回滾事務(wù)。這時可以使用線程的UncaughtExceptionHandler進(jìn)行異常處理,UncaughtExceptionHandler名字意味著處理未捕獲的異常。更明確的說,它處理未捕獲的運行時異常。

如下代碼
線程出要使用
①處要拋出異常
②處要捕捉異常,并且要拋出RuntimeException
③處手動處理回滾邏輯

@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......  
   
    }  
   
}  

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

相關(guān)文章

  • Java并發(fā)編程之Semaphore(信號量)詳解及實例

    Java并發(fā)編程之Semaphore(信號量)詳解及實例

    這篇文章主要介紹了Java并發(fā)編程之Semaphore(信號量)詳解及實例的相關(guān)資料,需要的朋友可以參考下
    2017-06-06
  • mac 安裝java1.8的過程詳解

    mac 安裝java1.8的過程詳解

    這篇文章主要介紹了mac 安裝java1.8,包括下載過程及配置環(huán)境相關(guān)知識介紹,本文結(jié)合實例代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2023-09-09
  • 解決Maven中的依賴導(dǎo)包問題(組合技巧)

    解決Maven中的依賴導(dǎo)包問題(組合技巧)

    自從我開始接觸了以spring為框架的項目學(xué)習(xí)后,這個maven導(dǎo)包老是出現(xiàn)問題,每次在這個上面花費好多時間,于是乎打算寫一個秘籍出來,這篇文章主要介紹了解決Maven中的依賴導(dǎo)包問題,需要的朋友可以參考下
    2023-11-11
  • SpringBoot整合Guava Cache實現(xiàn)全局緩存的示例代碼

    SpringBoot整合Guava Cache實現(xiàn)全局緩存的示例代碼

    這篇文章主要介紹了SpringBoot整合Guava Cache實現(xiàn)全局緩存,Guava Cache是Google Guava庫中的一個模塊,提供了基于內(nèi)存的本地緩存實現(xiàn),文中介紹了SpringBoot整合使用Guava Cache的具體步驟,需要的朋友可以參考下
    2024-03-03
  • SpringBoot集成canal實現(xiàn)示例解析

    SpringBoot集成canal實現(xiàn)示例解析

    這篇文章主要為大家介紹了springboot整合canal的示例實現(xiàn)解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多多進(jìn)步,早日升職加薪
    2022-02-02
  • 關(guān)于Java中的dozer對象轉(zhuǎn)換問題

    關(guān)于Java中的dozer對象轉(zhuǎn)換問題

    Dozer是Java?Bean到Java?Bean映射器,它以遞歸方式將數(shù)據(jù)從一個對象復(fù)制到另一個對象,這篇文章主要介紹了Java中的dozer對象轉(zhuǎn)換的操作方法,需要的朋友可以參考下
    2022-08-08
  • Java多線程之條件對象Condition

    Java多線程之條件對象Condition

    這篇文章主要介紹了Java多線程之條件對象Condition,Condition中的await()方法相當(dāng)于Object的wait()方法,Condition中的signal()方法相當(dāng)于Object的notify()方法,Condition中的signalAll()相當(dāng)于Object的notifyAll()方法,接下來和小編一起進(jìn)入文章了解更具體的內(nèi)容
    2021-10-10
  • JavaWeb response和request對象原理及實例解析

    JavaWeb response和request對象原理及實例解析

    這篇文章主要介紹了JavaWeb response和request對象原理及實例解析,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2020-11-11
  • SpringBoot?屬性配置中獲取值的方式

    SpringBoot?屬性配置中獲取值的方式

    這篇文章主要介紹了SpringBoot?屬性配置中獲取值的方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-02-02
  • Java 中 Map 集合的三種遍歷方式小結(jié)

    Java 中 Map 集合的三種遍歷方式小結(jié)

    這篇文章主要介紹了Java 中 Map 集合的三種遍歷方式,每種遍歷方式結(jié)合示例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2022-12-12

最新評論