最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

解讀@Transactional失效的幾種情況

 更新時間:2024年08月06日 11:20:18   作者:Q z1997  
這篇文章主要介紹了@Transactional失效的幾種情況,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教

Spring事務(wù)管理方式

  • 編碼式事務(wù)管理:將事務(wù)控制代碼編寫在業(yè)務(wù)代碼之中。
  • 聲明式事務(wù)管理:基于AOP(面向切面編程),事務(wù)管理與業(yè)務(wù)邏輯解耦。

聲明式事務(wù)管理的兩種實(shí)現(xiàn):

  • (1)在配置文件(xml)中配置。
  • (2)基于@Transactional注解。

@Transactional使用起來方便,但也需要注意引起@Transactional失效的場景,本文總結(jié)了七種情況,下面進(jìn)行逐一分析:

一、數(shù)據(jù)庫本身不支持

MySql 的 MyISAM 引擎不支持回滾,如果需要自動回滾事務(wù),需要將MySql的引擎設(shè)置成InnoDB;

二、注解的方法是否為public

//@Transactional注解在private方法上會失效
@Transactional
private void deleteUser() throws MyException{
    userMapper.deleteUserA();
    int i = 1/0;
    userMapper.deleteUserB();
}

idea直接會給出提示Methods annotated with ‘@Transactional’ must be overridable ,原理很簡單,private修飾的方式,spring無法生成動態(tài)代理,AOP代理分別在intercept()和invoke()方法判斷是否進(jìn)行事務(wù)攔截,這兩個方法都會間接調(diào)用AbstractFallbackTransactionAttributeSource類的computeTransactionAttribute方法來獲取事務(wù)控制的相關(guān)屬性。

這其中有以下一段代碼

    /**
     * Same signature as {@link #getTransactionAttribute}, but doesn't cache the result.
     * {@link #getTransactionAttribute} is effectively a caching decorator for this method.
     * <p>As of 4.1.8, this method can be overridden.
     * @since 4.1.8
     * @see #getTransactionAttribute
     */
    protected TransactionAttribute computeTransactionAttribute(Method method, Class<?> targetClass) {
        // Don't allow no-public methods as required.
        if (allowPublicMethodsOnly() && !Modifier.isPublic(method.getModifiers())) {
            return null;
        }
    //...
  }

這段代碼會導(dǎo)致no-public的方法無法進(jìn)入事務(wù)控制,所以一定要確保自己需要進(jìn)行事務(wù)控制的方法包含public修飾符。

三、異常處理不當(dāng)

當(dāng)異常被捕獲后,并且沒有再拋出,那么deleteUserA是不會回滾的,例如:

@Transactional
public void deleteUser() {
    userMapper.deleteUserA();
    try {
        int i = 1 / 0;
        userMapper.deleteUserB();
    } catch (Exception e) {
        e.printStackTrace();
    }
}

異步雖然拋出了,但是拋出的是非RuntimeException類型的異常,依舊不會生效,例如:

@Transactional
public void deleteUser() throws MyException{
    userMapper.deleteUserA();
    try {
        int i = 1 / 0;
        userMapper.deleteUserB();
    } catch (Exception e) {
        throw new MyException();
    }
}

注解為事務(wù)范圍的方法中,事務(wù)的回滾僅僅對于unchecked的異常有效。對于checked異常無效。也就是說事務(wù)回滾僅僅發(fā)生在,出現(xiàn)RuntimeException或Error的時候。通俗一點(diǎn)就是:代碼中出現(xiàn)的空指針等異常,會被回滾。而文件讀寫、網(wǎng)絡(luò)超時問題等,spring就沒法回滾了。

解決方案:如果指定了回滾異常類型為Exception,那么就可以回滾Checked類型異常了。

@Transactional(rollbackFor = Exception.class)

java里面將派生于Error或者RuntimeException(比如空指針,1/0)的異常稱為unchecked異常,其他繼承自java.lang.Exception得異常統(tǒng)稱為Checked Exception,如IOException、TimeoutException等

四、方法內(nèi)部直接調(diào)用

如果先調(diào)用deleteUser(),那么deleteUserA()是不會回滾的,其原因就是@Transactional根本沒生成代理,例如:

public void deleteUser() throws MyException{
    deleteUser2(); // 事物失效
}

@Transactional
public void deleteUser2() throws MyException{
    userMapper.deleteUserA();
    int i = 1 / 0;
    userMapper.deleteUserB();
}

五、多數(shù)據(jù)源事物配置問題

項(xiàng)目中沒有配置事務(wù)管理器,需要在配置類或者配置文件中配置,因?yàn)轫?xiàng)目是多數(shù)據(jù)源的,所以要區(qū)別配置不同數(shù)據(jù)源的事務(wù)管理器,如下:

    @Primary
    @Bean(name = "db1")
    public DataSource getDataSource() {
        return createDataSource();
    }
    @Bean(name = "db1TransactionManager")
    public PlatformTransactionManager txManager(@Qualifier("db1") DataSource dataSource) {
        return new DataSourceTransactionManager(dataSource);
    }

   @Bean(name = "db2")
   public DataSource getDataSource() {
       return buildDataSource();
   }
   @Bean(name = "db2TransactionManager")
   public PlatformTransactionManager txManager(@Qualifier("db2") DataSource dataSource) {
       return new DataSourceTransactionManager(dataSource);
   }

可以看到,兩個事務(wù)管理器配置了不同的beanName,接下來只需要 在需要事務(wù)控制的位置加上該事務(wù)管理器的name就可以完美解決!

   @Override
   @Transactional(value = "db1TransactionManager",rollbackFor = Exception.class)
   public int updateOrInsert(BaseRequest<BankTemplateDto> param) {
      ...
   }

六、新開啟一個線程

如下的方式deleteUserA()也不會回滾,因?yàn)閟pring實(shí)現(xiàn)事務(wù)的原理是通過ThreadLocal把數(shù)據(jù)庫連接綁定到當(dāng)前線程中,新開啟一個線程獲取到的連接就不是同一個了,例如:

@Transactional
public void deleteUser() throws MyException{
    userMapper.deleteUserA();
    try {
        //休眠1秒,保證deleteUserA先執(zhí)行
        Thread.sleep(1000);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
    new Thread(() -> {
        int i = 1/0;
        userMapper.deleteUserB();
    }).start();    
}

七、事務(wù)傳播屬性設(shè)置錯誤

注意傳播屬性的設(shè)置,一般情況下,propagation屬性無需配置。會使用默認(rèn)配置,即:PROPAGATION_REQUIRED,有些propagation屬性會導(dǎo)致事務(wù)不會觸發(fā),一定要注意:

  • PROPAGATION_SUPPORTS: 如果存在事務(wù),則進(jìn)入事務(wù);否則,以非事務(wù)方式運(yùn)行。
  • PROPAGATION_NOT_SUPPORTED: 如果存在事務(wù),則掛起事務(wù),并以非事務(wù)方式運(yùn)行。
  • PROPAGATION_NEVER: 以非事務(wù)形式運(yùn)行,如果存在事務(wù),則拋出異常。

總結(jié)

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

相關(guān)文章

  • Java數(shù)據(jù)敏感詞轉(zhuǎn)換成符號的方法詳解

    Java數(shù)據(jù)敏感詞轉(zhuǎn)換成符號的方法詳解

    在某個論壇下用戶可以隨意留言,為了防止不法分子在網(wǎng)上任意沖浪,需要對一些敏感詞匯進(jìn)行一些校驗(yàn),所以這篇文章給大家介紹了Java數(shù)據(jù)敏感詞轉(zhuǎn)換成符號的方法,需要的朋友可以參考下
    2024-03-03
  • SpringMvc接收參數(shù)方法總結(jié)(必看篇)

    SpringMvc接收參數(shù)方法總結(jié)(必看篇)

    下面小編就為大家?guī)硪黄猄pringMvc接收參數(shù)方法總結(jié)(必看篇)。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-06-06
  • 詳解使用Maven開發(fā)Web應(yīng)用詳細(xì)步驟

    詳解使用Maven開發(fā)Web應(yīng)用詳細(xì)步驟

    這篇文章主要介紹了詳解使用Maven開發(fā)Web應(yīng)用詳細(xì)步驟,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-11-11
  • java 如何給對象中的包裝類設(shè)置默認(rèn)值

    java 如何給對象中的包裝類設(shè)置默認(rèn)值

    這篇文章主要介紹了java 如何給對象中的包裝類設(shè)置默認(rèn)值,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-03-03
  • 深入解析Java的設(shè)計(jì)模式編程中單例模式的使用

    深入解析Java的設(shè)計(jì)模式編程中單例模式的使用

    這篇文章主要介紹了深入解析Java的設(shè)計(jì)模式編程中單例模式的使用,一般來說將單例模式分為餓漢式單例和懶漢式單例,需要的朋友可以參考下
    2016-02-02
  • springboot實(shí)現(xiàn)token驗(yàn)證登陸狀態(tài)的示例代碼

    springboot實(shí)現(xiàn)token驗(yàn)證登陸狀態(tài)的示例代碼

    本文主要介紹了spring?boot?實(shí)現(xiàn)token驗(yàn)證登陸狀態(tài),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2024-07-07
  • Springboot @Value使用代碼實(shí)例

    Springboot @Value使用代碼實(shí)例

    這篇文章主要介紹了Springboot @Value使用代碼實(shí)例,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2019-11-11
  • 淺析如何在SpringBoot上傳中將MultipartFile轉(zhuǎn)File對象

    淺析如何在SpringBoot上傳中將MultipartFile轉(zhuǎn)File對象

    在我們開發(fā) Spring Boot Web 應(yīng)用中,文件上傳通常通過 MultipartFile 接口接收,但有時我們需要將 MultipartFile 轉(zhuǎn)成標(biāo)準(zhǔn)的 java.io.File 對象,下面我們就來看看具體實(shí)現(xiàn)吧
    2025-08-08
  • 一文告訴你為什么要重寫hashCode()方法和equals()方法

    一文告訴你為什么要重寫hashCode()方法和equals()方法

    本篇文章帶大家了解一下為什么重寫hashCode()方法和equals()方法,文中有非常詳細(xì)的說明以及代碼示例,對正在學(xué)習(xí)java的小伙伴們很有幫助,需要的朋友可以參考下
    2021-05-05
  • Java中Future接口詳解

    Java中Future接口詳解

    這篇文章主要介紹了Java中Future接口詳解,本文通過案例給大家詳細(xì)講解了Java中Future接口,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2023-04-04

最新評論

兰溪市| 咸宁市| 株洲县| 滦南县| 防城港市| 清涧县| 宜黄县| 洪泽县| 嘉荫县| 五河县| 和顺县| 麻江县| 色达县| 青阳县| 玛沁县| 永福县| 鞍山市| 道孚县| 郎溪县| 武功县| 苍梧县| 平定县| 贵南县| 建阳市| 金塔县| 连云港市| 承德县| 武穴市| 印江| 乐陵市| 白河县| 长海县| 郑州市| 攀枝花市| 陵川县| 枣庄市| 桂平市| 岳普湖县| 莆田市| 梓潼县| 芮城县|