真实的国产乱ⅩXXX66竹夫人,五月香六月婷婷激情综合,亚洲日本VA一区二区三区,亚洲精品一区二区三区麻豆

成都創(chuàng)新互聯(lián)網(wǎng)站制作重慶分公司

Spring中@Transactional事務(wù)不生效如何解決

這期內(nèi)容當(dāng)中小編將會(huì)給大家?guī)碛嘘P(guān)Spring中@Transactional事務(wù)不生效如何解決,文章內(nèi)容豐富且以專業(yè)的角度為大家分析和敘述,閱讀完這篇文章希望大家可以有所收獲。

成都創(chuàng)新互聯(lián)服務(wù)項(xiàng)目包括康縣網(wǎng)站建設(shè)、康縣網(wǎng)站制作、康縣網(wǎng)頁(yè)制作以及康縣網(wǎng)絡(luò)營(yíng)銷策劃等。多年來,我們專注于互聯(lián)網(wǎng)行業(yè),利用自身積累的技術(shù)優(yōu)勢(shì)、行業(yè)經(jīng)驗(yàn)、深度合作伙伴關(guān)系等,向廣大中小型企業(yè)、政府機(jī)構(gòu)等提供互聯(lián)網(wǎng)行業(yè)的解決方案,康縣網(wǎng)站推廣取得了明顯的社會(huì)效益與經(jīng)濟(jì)效益。目前,我們服務(wù)的客戶以成都為中心已經(jīng)輻射到康縣省份的部分城市,未來相信會(huì)繼續(xù)擴(kuò)大服務(wù)區(qū)域并繼續(xù)獲得客戶的支持與信任!

一、Spring事務(wù)管理方式

事務(wù)管理在系統(tǒng)開發(fā)中是不可缺少的一部分,Spring提供了很好事務(wù)管理機(jī)制,主要分為編程式事務(wù)聲明式事務(wù)兩種。

  1. 編碼式事務(wù)管理:將事務(wù)控制代碼編寫在業(yè)務(wù)代碼之中。

  2. 聲明式事務(wù)管理:基于AOP(面向切面編程),事務(wù)管理與業(yè)務(wù)邏輯解耦。兩種實(shí)現(xiàn):(1)在配置文件(xml)中配置。(2)基于@Transactional注解。

二、@Transactional注解可以作用于哪些地方?

@Transactional 可以作用在接口、類方法

  • 作用于類:當(dāng)把@Transactional 注解放在類上時(shí),表示所有該類的public方法都配置相同的事務(wù)屬性信息。

  • 作用于方法:當(dāng)類配置了@Transactional,方法也配置了@Transactional,方法的事務(wù)會(huì)覆蓋類的事務(wù)配置信息。

  • 作用于接口:不推薦這種使用方法,因?yàn)橐坏?biāo)注在Interface上并且配置了Spring AOP 使用CGLib動(dòng)態(tài)代理,將會(huì)導(dǎo)致@Transactional注解失效

三、@Transactional失效場(chǎng)景

1. 數(shù)據(jù)庫(kù)本身不支持

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

2. 注解的方法是否為public
//@Transactional注解在private方法上會(huì)失效@Transactionalprivate 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無法生成動(dòng)態(tài)代理,AOP代理分別在intercept()和invoke()方法判斷是否進(jìn)行事務(wù)攔截,這兩個(gè)方法都會(huì)間接調(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.
     * 

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的方法無法進(jìn)入事務(wù)控制,所以一定要確保自己需要進(jìn)行事務(wù)控制的方法包含public修飾符。

3. 異常處理不當(dāng)

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

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

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

@Transactionalpublic 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ù)回滾僅僅發(fā)生在,出現(xiàn)RuntimeException或Error的時(shí)候。通俗一點(diǎn)就是:代碼中出現(xiàn)的空指針等異常,會(huì)被回滾。而文件讀寫、網(wǎng)絡(luò)超時(shí)問題等,spring就沒法回滾了。
解決方案:如果指定了回滾異常類型為Exception,那么就可以回滾Checked類型異常了。

@Transactional(rollbackFor = Exception.class)

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

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

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

public void deleteUser() throws MyException{deleteUser2(); // 事物失效}@Transactionalpublic void deleteUser2() throws MyException{userMapper.deleteUserA();int i = 1 / 0;userMapper.deleteUserB();}
5. 多數(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);
   }

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

   @Override
   @Transactional(value = "db1TransactionManager",rollbackFor = Exception.class)
   public int updateOrInsert(BaseRequest param) {  ...
   }
6. 新開啟一個(gè)線程

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

@Transactionalpublic 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();    }
7. 事務(wù)傳播屬性設(shè)置錯(cuò)誤

注意傳播屬性的設(shè)置,一般情況下,propagation屬性無需配置。會(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ù),則拋出異常。

四、@Transactional注有哪些屬性?

propagation屬性

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

  • 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ù)。(當(dāng)類A中的 a 方法用默認(rèn)Propagation.REQUIRED模式,類B中的 b方法加上采用 Propagation.REQUIRES_NEW模式,然后在 a 方法中調(diào)用 b方法操作數(shù)據(jù)庫(kù),然而 a方法拋出異常后,b方法并沒有進(jìn)行回滾,因?yàn)?code>Propagation.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 屬性

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

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

readOnly 屬性

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

rollbackFor 屬性

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

noRollbackFor屬性**

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

上述就是小編為大家分享的Spring中@Transactional事務(wù)不生效如何解決了,如果剛好有類似的疑惑,不妨參照上述分析進(jìn)行理解。如果想知道更多相關(guān)知識(shí),歡迎關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道。


分享標(biāo)題:Spring中@Transactional事務(wù)不生效如何解決
網(wǎng)站網(wǎng)址:http://weahome.cn/article/jscpgi.html

其他資訊

在線咨詢

微信咨詢

電話咨詢

028-86922220(工作日)

18980820575(7×24)

提交需求

返回頂部