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

解讀@Transactional失效的幾種情況

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

Spring事務(wù)管理方式

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

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

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

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

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

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

二、注解的方法是否為public

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

idea直接會(huì)給出提示Methods annotated with ‘@Transactional’ must be overridable ,原理很簡(jiǎn)單,private修飾的方式,spring無(wú)法生成動(dòng)態(tài)代理,AOP代理分別在intercept()和invoke()方法判斷是否進(jìn)行事務(wù)攔截,這兩個(gè)方法都會(huì)間接調(diào)用AbstractFallbackTransactionAttributeSource類(lèi)的computeTransactionAttribute方法來(lái)獲取事務(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;
        }
    //...
  }

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

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

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

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

異步雖然拋出了,但是拋出的是非RuntimeException類(lèi)型的異常,依舊不會(huì)生效,例如:

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

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

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

@Transactional(rollbackFor = Exception.class)

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

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

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

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

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

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

項(xiàng)目中沒(méi)有配置事務(wù)管理器,需要在配置類(lèi)或者配置文件中配置,因?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);
   }

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

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

六、新開(kāi)啟一個(gè)線程

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

@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è)置錯(cuò)誤

注意傳播屬性的設(shè)置,一般情況下,propagation屬性無(wú)需配置。會(huì)使用默認(rèn)配置,即:PROPAGATION_REQUIRED,有些propagation屬性會(huì)導(dǎo)致事務(wù)不會(huì)觸發(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é)

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

相關(guān)文章

  • Springboot中實(shí)現(xiàn)接口冪等性的4種方案小結(jié)

    Springboot中實(shí)現(xiàn)接口冪等性的4種方案小結(jié)

    本文主要介紹了Springboot中實(shí)現(xiàn)接口冪等性,包含數(shù)據(jù)庫(kù)的冪等,數(shù)據(jù)庫(kù)的冪等,Redis的冪等性和Token + 時(shí)間戳的冪等性,具有一定的參考價(jià)值,感興趣的可以了解一下
    2024-03-03
  • Future與FutureTask接口實(shí)現(xiàn)示例詳解

    Future與FutureTask接口實(shí)現(xiàn)示例詳解

    這篇文章主要為大家介紹了Future與FutureTask接口實(shí)現(xiàn)示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-10-10
  • 總結(jié)Java對(duì)象被序列化的兩種方法

    總結(jié)Java對(duì)象被序列化的兩種方法

    今天給大家?guī)?lái)的是關(guān)于Java的相關(guān)知識(shí),文章圍繞著Java對(duì)象被序列化的兩種方法展開(kāi),文中有非常詳細(xì)的介紹及代碼示例,需要的朋友可以參考下
    2021-06-06
  • 基于Java驗(yàn)證jwt token代碼實(shí)例

    基于Java驗(yàn)證jwt token代碼實(shí)例

    這篇文章主要介紹了基于Java驗(yàn)證jwt token代碼實(shí)例,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2019-12-12
  • 詳解Java注解教程及自定義注解

    詳解Java注解教程及自定義注解

    這篇文章主要為大家詳細(xì)介紹了Java注解教程及自定義注解,幫助大家更好地學(xué)習(xí)Java注解,感興趣的小伙伴們可以參考一下
    2016-01-01
  • Spring Security認(rèn)證機(jī)制源碼層探究

    Spring Security認(rèn)證機(jī)制源碼層探究

    SpringSecurity是基于Filter實(shí)現(xiàn)認(rèn)證和授權(quán),底層通過(guò)FilterChainProxy代理去調(diào)用各種Filter(Filter鏈),F(xiàn)ilter通過(guò)調(diào)用AuthenticationManager完成認(rèn)證 ,通過(guò)調(diào)用AccessDecisionManager完成授權(quán)
    2023-03-03
  • Java JVM虛擬機(jī)運(yùn)行機(jī)制

    Java JVM虛擬機(jī)運(yùn)行機(jī)制

    JVM(Java虛擬機(jī))一種用于計(jì)算設(shè)備的規(guī)范,可用不同的方式(軟件或硬件)加以實(shí)現(xiàn)。接下來(lái)通過(guò)本文給大家簡(jiǎn)單介紹Java JVM虛擬機(jī)運(yùn)行機(jī)制,感興趣的朋友一起看看吧
    2017-03-03
  • springcloud feign調(diào)其他微服務(wù)時(shí)參數(shù)是對(duì)象的問(wèn)題

    springcloud feign調(diào)其他微服務(wù)時(shí)參數(shù)是對(duì)象的問(wèn)題

    這篇文章主要介紹了springcloud feign調(diào)其他微服務(wù)時(shí)參數(shù)是對(duì)象的問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-03-03
  • 詳解Java中switch的新特性

    詳解Java中switch的新特性

    這篇文章主要介紹了Java中switch的新特性,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2023-05-05
  • java按字節(jié)截取帶有漢字的字符串的解法(推薦)

    java按字節(jié)截取帶有漢字的字符串的解法(推薦)

    下面小編就為大家?guī)?lái)一篇java按字節(jié)截取帶有漢字的字符串的解法(推薦)。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2016-09-09

最新評(píng)論