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

spring中12種@Transactional的失效場景(小結)

 更新時間:2022年01月05日 08:59:06   作者:superjava_  
日常我們進行業(yè)務開發(fā)時,基本上使用的都是聲明式事務,即為使用@Transactional注解的方式,本文主要介紹了spring中12種@Transactional的失效場景,感興趣的小伙伴們可以參考一下

數(shù)據(jù)庫事務是后端開發(fā)中不可缺少的一塊知識點。Spring為了更好的支撐我們進行數(shù)據(jù)庫操作,在框架中支持了兩種事務管理的方式: 編程式事務聲明式事務

日常我們進行業(yè)務開發(fā)時,基本上使用的都是聲明式事務,即為使用@Transactional注解的方式。

常規(guī)使用時,Spring能幫我們很好的實現(xiàn)數(shù)據(jù)庫的ACID (這里需要注意哦,Spring只是進行了編程上的事務,最終數(shù)據(jù)上的事務還是有數(shù)據(jù)庫實現(xiàn)的) 。

但是,只要是人寫的代碼,就一定會有Bug。

如果我們不了解@Transactional的失效場景或者說踩坑點,那么在業(yè)務開發(fā)的過程中總是會出現(xiàn)一些匪夷所思的Bug。

同樣它也是面試時高頻的考點哦!

本文將羅列@Transactional的失效場景,并分析其失效原因。

一、失效場景集一:代理不生效

Spring中對注解解析的尿性都是基于代理的,如果目標方法無法被Spring代理到,那么它將無法被Spring進行事務管理。

Spring生成代理的方式有兩種:

  • 基于接口的JDK動態(tài)代理,要求目標代理類需要實現(xiàn)一個接口才能被代理
  • 基于實現(xiàn)目標類子類的CGLIB代理

Spring在2.0之前,目標類如果實現(xiàn)了接口,則使用JDK動態(tài)代理方式,否則通過CGLIB子類的方式生成代理。

而在2.0版本之后,如果不在配置文件中顯示的指定spring.aop.proxy-tartget-class的值,默認情況下生成代理的方式為CGLIB,如下圖

image-20211230104332833.jpg

順著代理的思路,我們來看看哪些情況會因為代理不生效導致事務管控失敗。

(1)將注解標注在接口方法上

@Transactional是支持標注在方法與類上的。一旦標注在接口上,對應接口實現(xiàn)類的代理方式如果是CGLIB,將通過生成子類的方式生成目標類的代理,將無法解析到@Transactional,從而事務失效。

這種錯誤我們還是犯得比較少的,基本上我們都會將注解標注在接口的實現(xiàn)類方法上,官方也不推薦這種。

(2)被final、static關鍵字修飾的類或方法

CGLIB是通過生成目標類子類的方式生成代理類的,被final、static修飾后,無法繼承父類與父類的方法。

(3)類方法內部調用

事務的管理是通過代理執(zhí)行的方式生效的,如果是方法內部調用,將不會走代理邏輯,也就調用不到了。

例如

image-20211230143307601.jpg

createUser中調用了內部方法createUser1,并且createUser1方法上設置了事務傳播策略為:REQUIRES_NEW,但是因為是內部直接調用,createUser1不能不代理處理,無法進行事務管理。在createUser1方法拋出異常后就插入數(shù)據(jù)失敗了。

但是這種操作在我們業(yè)務開發(fā)的過程中貌似還挺常見的,怎么樣才能保證其成功呢?

方式1:新建一個Service,將方法遷移過去,有點麻瓜。

方式2:在當前類注入自己,調用createUser1時通過注入的userService調用

image-20211230143808766.jpg

方式3:通過AopContext.currentProxy()獲取代理對象

image-20211230143957694.jpg

道理類似于方式2,就是為了通過代理來訪問內部方法

(4)當前類沒有被Spring管理

這個沒什么好說的,都沒有被Spring管理成為IOC容器中的一個bean,更別說被事務切面代理到了。

這種Bug看上去比較蠢,但沒準真的有人犯錯。

二、失效場景集二:框架或底層不支持的功能

這類失效場景主要聚焦在框架本身在解析@Transactional時的內部支持。如果使用的場景本身就是框架不支持的,那事務也是無法生效的。

(1)非public修飾的方法

我們在標有@Transactional的任意方法上打個斷點,在idea內能看到事務切面點如下圖所示

image-20211230135414452.jpg

點擊去這個方法,在開頭有這么一個調用

image-20211230140357800.jpg

繼續(xù)進去

image-20211230140438344.jpg

就能看到這么一句話了

image-20211230140504211.jpg

不支持非public修飾的方法進行事務管理。

(2)多線程調用

跟上面一樣的的操作,我們能夠逐層進入到TransactionAspectSupport.prepareTransactionInfo方法。

注意看以下這段話

image-20211230161110957.jpg

從這里我們得知,事務信息是跟線程綁定的。

因此在多線程環(huán)境下,事務的信息都是獨立的,將會導致Spring在接管事務上出現(xiàn)差異。

這個場景我們要尤其注意!

給大家舉個例子

主線程A調用線程B保存Id為1的數(shù)據(jù),然后主線程A等待線程B執(zhí)行完成再通過線程A查詢id為1的數(shù)據(jù)。

這時你會發(fā)現(xiàn)在主線程A中無法查詢到id為1的數(shù)據(jù)。因為這兩個線程在不同的Spring事務中,本質上會導致它們在Mysql中存在不同的事務中。

Mysql中通過MVCC保證了線程在快照讀時只讀取小于當前事務號的數(shù)據(jù),在線程B顯然事務號是大于線程A的,因此查詢不到數(shù)據(jù)。

(3)數(shù)據(jù)庫本身不支持事務

比如Mysql的Myisam存儲引擎是不支持事務的,只有innodb存儲引擎才支持。

這個問題出現(xiàn)的概率極其小,因為Mysql5之后默認情況下是使用innodb存儲引擎了。

但如果配置錯誤或者是歷史項目,發(fā)現(xiàn)事務怎么配都不生效的時候,記得看看存儲引擎本身是否支持事務。

(4)未開啟事務

這個也是一個比較麻瓜的問題,在Springboot項目中已經(jīng)不存在了,已經(jīng)有DataSourceTransactionManagerAutoConfiguration默認開啟了事務管理。

但是在MVC項目中還需要在applicationContext.xml文件中,手動配置事務相關參數(shù)。如果忘了配置,事務肯定是不會生效的。

三、失效場景集三:錯誤使用@Transactional

注意啦注意啦,下面這幾種都是高頻會出現(xiàn)的Bug!

(1)錯誤的傳播機制

Spring支持了7種傳播機制,分別為:

image.jpg

上面不支持事務的傳播機制為:PROPAGATION_SUPPORTS,PROPAGATION_NOT_SUPPORTED,PROPAGATION_NEVER。

如果配置了這三種傳播方式的話,在發(fā)生異常的時候,事務是不會回滾的。

(2)rollbackFor屬性設置錯誤

image-20211230165715830.jpg

默認情況下事務僅回滾運行時異常和Error,不回滾受檢異常(例如IOException)。

因此如果方法中拋出了IO異常,默認情況下事務也會回滾失敗。

我們可以通過指定@Transactional(rollbackFor = Exception.class)的方式進行全異常捕獲。

(3)異常被內部catch

UserService

image-20211230171002480.jpg

UserService1

image-20211230171013646.jpg

如上代碼UserService調用了UserService1中的方法,并且捕獲了UserService1中拋出的異常。

你將能看到控制臺出現(xiàn)這樣一個報錯:

 org.springframework.transaction.UnexpectedRollbackException: Transaction rolled back because it has been marked as rollback-only

默認情況下標注了@Transactional注解的方法的事務傳播機制是REQUIRED,它的特性是支持當前事務,也就說加入當前事務。我們在UserService中開始事務,然后再UserService1中拋出異?;貪LUserService中的事務,將其標記為只讀。

但是在UserSevice中我們捕獲了異常,此時UserService上的事務認為正常提交事務。最后在提交時發(fā)現(xiàn)事務只讀,已經(jīng)被回滾,則拋出了上述異常。

因此這里如果需要對特定的異常進行捕獲處理,記得再次將異常拋出,讓最外層的事務感知到。

(4)嵌套事務

上面是我想同時回滾UserService與UserService1。但是也會有這種場景只想回滾UserService1中報錯的數(shù)據(jù)庫操作,不影響主邏輯UserService中的數(shù)據(jù)落庫。

有兩種方式可以實現(xiàn)上述邏輯:

1.直接在UserService1內的整個方法用try/catch包住

2.在UserService1使用Propagation.REQUIRES_NEW傳播機制

image-20211230173219220.jpg

四、總結

本文為大家分析@Transactional注解使用過程中失效的12種場景

image-20211230224957141.jpg

最后,@Transactional注解雖香,但是復雜業(yè)務邏輯下,為了更好的管理事務與把控業(yè)務處理時事務的細粒度,我還是推薦大家使用編程式事務。

到此這篇關于spring中12種@Transactional的失效場景(小結)的文章就介紹到這了,更多相關spring @Transactional 失效場景 內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

相關文章

  • socket編程時的發(fā)送與接收數(shù)據(jù)時的問題解析

    socket編程時的發(fā)送與接收數(shù)據(jù)時的問題解析

    這篇文章主要為大家介紹了socket編程時的發(fā)送與接收數(shù)據(jù)時的問題解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2023-06-06
  • 淺談JAVA設計模式之代理模式

    淺談JAVA設計模式之代理模式

    這篇文章主要介紹了JAVA設計模式之代理模式的的相關資料,文中代碼非常詳細,供大家參考和學習,感興趣的朋友可以了解下
    2020-06-06
  • SpringBoot零基礎入門之基本操作與概念

    SpringBoot零基礎入門之基本操作與概念

    這篇文章主要介紹了SpringBoot的概念、創(chuàng)建和運行,本文通過實例代碼給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2022-07-07
  • Java函數(shù)式編程(七):MapReduce

    Java函數(shù)式編程(七):MapReduce

    這篇文章主要介紹了Java函數(shù)式編程(七):MapReduce,本文是系列文章的第7篇,其它文章請參閱本文底部的相關文章,需要的朋友可以參考下
    2014-09-09
  • Mybatis實現(xiàn)動態(tài)建表代碼實例

    Mybatis實現(xiàn)動態(tài)建表代碼實例

    這篇文章主要介紹了Mybatis實現(xiàn)動態(tài)建表代碼實例,解釋一下,就是指根據(jù)傳入的表名,動態(tài)地創(chuàng)建數(shù)據(jù)庫表,以供后面的業(yè)務場景使用,
    而使用 Mybatis 的動態(tài) SQL,就能很好地為我們解決這個問題,需要的朋友可以參考下
    2023-10-10
  • 淺談Java泛型通配符解決了泛型的許多詬病(如不能重載)

    淺談Java泛型通配符解決了泛型的許多詬病(如不能重載)

    下面小編就為大家?guī)硪黄獪\談Java泛型通配符解決了泛型的許多詬病(如不能重載)。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2016-10-10
  • java利用htmlparser獲取html中想要的代碼具體實現(xiàn)

    java利用htmlparser獲取html中想要的代碼具體實現(xiàn)

    這篇文章主要介紹了java利用htmlparser獲取html中想要的代碼具體實現(xiàn),需要的朋友可以參考下
    2014-02-02
  • MyBatis異常java.sql.SQLSyntaxErrorException的問題解決

    MyBatis異常java.sql.SQLSyntaxErrorException的問題解決

    使用mybatis插入數(shù)據(jù)時出現(xiàn)java.sql.SQLSyntaxErrorException異常,本文就來介紹一下MyBatis異常的問題解決,具有一定的參考價值,感興趣的可以了解一下
    2023-08-08
  • Java類變量和成員變量初始化過程的應用介紹

    Java類變量和成員變量初始化過程的應用介紹

    昨天看了一本叫做《突破程序員基本功的16課》的書,個人感覺還可以,主要對Java的技巧進行了一些深入的講解,讓我對類的初始化和對象的創(chuàng)建有了新的認識
    2013-04-04
  • idea maven pom不自動更新的解決方法

    idea maven pom不自動更新的解決方法

    這篇文章主要介紹了idea maven pom不自動更新的解決方法,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2020-08-08

最新評論