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

Spring注解@Transactional失效的場(chǎng)景分析

 更新時(shí)間:2023年07月18日 11:02:41   作者:京東云開(kāi)發(fā)者  
在使用Spring中事務(wù)注解@Transactional時(shí)會(huì)存在幾種場(chǎng)景下該注解失效,即不能按照預(yù)期封裝成一個(gè)事務(wù)操作,于是本文文將對(duì)該注解進(jìn)行學(xué)習(xí)并對(duì)相關(guān)失效場(chǎng)景進(jìn)行分析,需要的朋友可以參考下

一、前言

emm,又又又踩坑啦。這次的需求主要是對(duì)逾期計(jì)算的需求任務(wù)進(jìn)行優(yōu)化,現(xiàn)有的計(jì)算任務(wù)運(yùn)行時(shí)間太長(zhǎng)了。簡(jiǎn)單描述下此次的問(wèn)題:在項(xiàng)目中進(jìn)行多個(gè)數(shù)據(jù)庫(kù)執(zhí)行操作時(shí),我們期望的是將其整個(gè)封裝成一個(gè)事務(wù),要么全部成功,或者全部失敗,然而在自測(cè)異常場(chǎng)景時(shí)發(fā)現(xiàn),里面涉及的第一個(gè)數(shù)據(jù)狀態(tài)更新成功了,但是后面的數(shù)據(jù)在插入出現(xiàn)異常,后面查詢數(shù)據(jù)表發(fā)現(xiàn),該數(shù)據(jù)的狀態(tài)已經(jīng)被更新成功啦

emmm,查看代碼發(fā)現(xiàn)確實(shí)是使用了@Transactional注解沒(méi)問(wèn)啊。于是通過(guò)查詢網(wǎng)上相關(guān)資料發(fā)現(xiàn),在使用Spring中事務(wù)注解@Transactional時(shí)會(huì)存在幾種場(chǎng)景下該注解失效,即不能按照預(yù)期封裝成一個(gè)事務(wù)操作,于是對(duì)該注解進(jìn)行學(xué)習(xí)并對(duì)相關(guān)失效場(chǎng)景進(jìn)行分析,整理文章如下;

二、@Transactional注解失效場(chǎng)景實(shí)例驗(yàn)證

1、@Transactional注解屬性

屬性類(lèi)型描述
valueString可選的限定描述符,指定使用的事務(wù)管理器
propagationEnum:Propagation·可選的事務(wù)傳播行為設(shè)置
isolationEnum:Isolation可選的事務(wù)隔離級(jí)別設(shè)置
readOnlyboolean讀寫(xiě)或只讀事務(wù),默認(rèn)讀寫(xiě)
timeoutint事務(wù)超時(shí)時(shí)間設(shè)置
rollbackForClass對(duì)象數(shù)組,必須繼承自Throwable導(dǎo)致事務(wù)回滾的異常類(lèi)數(shù)組
rollbackForClassName類(lèi)名數(shù)組,必須繼承自Throwable導(dǎo)致事務(wù)回滾的異常類(lèi)名字?jǐn)?shù)組
noRollbackForClass對(duì)象數(shù)組,必須繼承自Throwable不會(huì)導(dǎo)致事務(wù)回滾的異常類(lèi)數(shù)組
noRollbackForClassName類(lèi)名數(shù)組,必須繼承自Throwable不會(huì)導(dǎo)致事務(wù)回滾的異常類(lèi)名字?jǐn)?shù)組

2、 propagation屬性

propagation代表事務(wù)的傳播行為,默認(rèn)值為Propagation.REQUIRED

屬性描述
Propagation.REQUIRED若當(dāng)前存在事務(wù)則加入該事務(wù),若不存在則創(chuàng)建一個(gè)新事務(wù)(默認(rèn))
Propagation.SUPPORTS若當(dāng)前存在事務(wù)則加入該事務(wù),若不存在則以非事務(wù)的方式繼續(xù)進(jìn)行
Propagation.MANDATORY若當(dāng)前存在事務(wù)則加入該事務(wù),若不存在則拋出異常
Propagation.REQUIRES_NEW重新創(chuàng)建一個(gè)新的事務(wù),若當(dāng)前存在事務(wù)則暫定當(dāng)前事務(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效果一樣

3、 @Transactional注解使用場(chǎng)景?

@Transactional注解可以作用在接口、類(lèi)、類(lèi)方法中。

  • 當(dāng)作用于類(lèi)時(shí),表示所有該類(lèi)的public方法都配置相同的事務(wù)屬性信息。

  • 當(dāng)作用于方法時(shí),當(dāng)類(lèi)配置了@Transactional注解,方法也配置了@Transactional,方法的事務(wù)會(huì)覆蓋類(lèi)的事務(wù)配置信息。

  • 當(dāng)作用于接口時(shí),不推薦使用,因?yàn)樵诮涌谑褂聾Transactional并且配置了Spring AOP使用CGLib動(dòng)態(tài)代理將會(huì)導(dǎo)致其失效。

4、 @Transactional注解失效場(chǎng)景?

  • @Transactional注解作用在非public修飾的方法上,會(huì)失效。

失效原因:在Spring AOP代理時(shí),TransactionInterceptor(事務(wù)攔截器)在目標(biāo)方法執(zhí)行前后進(jìn)行攔截,DynamicAdvisedInterceptor(CglibAopProxy的內(nèi)部類(lèi))的Intercept方法或JDKDynamicAopProxyinvoke方法會(huì)間接調(diào)用AbstractFallbackTransationAttributeSourcecomputeTransactionAttribute方法,獲取@Transactional注解的事務(wù)配置信息。

1 protected TransactionAttribute computeTransactionAttribute(Method method,
2    Class<?> targetClass) {
3        // Don't allow no-public methods as required.
4        if (allowPublicMethodsOnly() && !Modifier.isPublic(method.getModifiers())) {
5        return null;
6    }

此方法會(huì)檢查目標(biāo)方法的修飾符是否為public,非public作用域則不會(huì)獲取@transactional的屬性配置信息。其中protected、private修飾的方法上使用 @Transactional注解,事務(wù)會(huì)失效但不會(huì)有任何報(bào)錯(cuò)。

  • @Transactional注解屬性propagation設(shè)置錯(cuò)誤導(dǎo)致注解失效

失效原因:配置錯(cuò)誤, PROPAGATION_SUPPORTS、PROPAGATION_NOT_SUPPORTED、PROPAGATION_NEVER三種事務(wù)傳播方式不會(huì)發(fā)生回滾。

? 實(shí)例驗(yàn)證:寫(xiě)了一個(gè)demo進(jìn)行測(cè)試。demo主要功能如下:執(zhí)行兩次數(shù)據(jù)庫(kù)插入操作,并在擴(kuò)展信息字段中添加備注;

? 運(yùn)行結(jié)果如下,構(gòu)造的單號(hào)不存在訂單查詢?yōu)榭沼|發(fā)異常,觀察數(shù)據(jù)庫(kù)發(fā)現(xiàn),第一次數(shù)據(jù)庫(kù)插入操作已經(jīng)執(zhí)行成功,故而驗(yàn)證@Transactional注解失效;

  • @Transactional注解屬性rollbackFor設(shè)置錯(cuò)誤導(dǎo)致注解失效

rollbackFor可以指定能夠觸發(fā)事務(wù)回滾的異常類(lèi)型。Spring默認(rèn)拋出了unchecked異常(繼承自RuntimeException)或者Error才會(huì)回滾事務(wù)。若事務(wù)中拋出了其他類(lèi)型的異常,但卻期望Spring能夠回滾事務(wù),就需要指定rollbackFor屬性,否則就會(huì)失效。

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

比如類(lèi)demo中有方法A和B,方法B中使用@Transactional注解,方法A沒(méi)有注解,但是demo類(lèi)通過(guò)方法A調(diào)用方法B,像這種間接調(diào)用會(huì)導(dǎo)致方法B中的@Transactional事務(wù)注解失效。

失效原因:只有當(dāng)事務(wù)方法被當(dāng)前類(lèi)以外的代碼調(diào)用時(shí),才會(huì)有Spring生成的代理對(duì)象管理。(Spring AOP代理機(jī)制造成的)。

? 實(shí)例驗(yàn)證:demo中構(gòu)造場(chǎng)景為在同一個(gè)類(lèi)中,在test方法中添加@Transactional注解,querRiskScore方法中不添加該注解,然后在querRiskScore方法中調(diào)用test方法;觀察下多個(gè)插入操作是否會(huì)因?yàn)楫惓6袛嗷貪L;

? 運(yùn)行結(jié)果如下,還是通過(guò)構(gòu)造的單號(hào)不存在訂單查詢?yōu)榭沼|發(fā)異常,觀察數(shù)據(jù)庫(kù)發(fā)現(xiàn),第一次數(shù)據(jù)庫(kù)插入操作已經(jīng)執(zhí)行成功,第二次數(shù)據(jù)插入操作失敗,并沒(méi)有因?yàn)楫惓6|發(fā)事務(wù)操作,故而驗(yàn)證@Transactional注解方法間的調(diào)用會(huì)失效

  • 多線程任務(wù)可能導(dǎo)致@Transaction案例失效

失效原因:線程不屬于Spring托管,故線程不能夠默認(rèn)使用Spring的事務(wù),也不能獲取Spring注入的bean,在被Spring聲明式事務(wù)管理的方法內(nèi)開(kāi)啟多線程,多線程內(nèi)的方法不被事務(wù)控制。

  • 異常被方法內(nèi)catch捕獲導(dǎo)致@Transactional失效

比如B方法內(nèi)部拋了異常,而A方法此時(shí)try-catch了B方法的異常,則該事務(wù)不能正?;貪L。

失效原因:因?yàn)锽方法中拋出異常以后,標(biāo)識(shí)當(dāng)前事務(wù)需要rollback,但是A方法中由于你手動(dòng)的捕獲這個(gè)異常并進(jìn)行處理,A方法認(rèn)為當(dāng)前事務(wù)應(yīng)該正常commit,此時(shí)就出現(xiàn)前后不一致,會(huì)拋出org.springframework.transaction.UnexpectedRollbackException: Transaction rolled back because it has been marked as rollback-only異常。

? 實(shí)例驗(yàn)證:這個(gè)場(chǎng)景的本質(zhì)還是異常被捕獲導(dǎo)致無(wú)法正常的拋出,進(jìn)而導(dǎo)致@Transactional注解無(wú)法正常工作,我簡(jiǎn)化了下demo實(shí)例場(chǎng)景,構(gòu)造場(chǎng)景如下:在querRiskScore方法中添加@Transactional注解,然后在querRiskScore方法中對(duì)異常進(jìn)行捕獲;觀察下多個(gè)插入操作是否會(huì)因?yàn)楫惓6袛嗷貪L;

? 運(yùn)行結(jié)果如下,還是通過(guò)構(gòu)造的單號(hào)不存在訂單查詢?yōu)榭沼|發(fā)異常,但是我們?cè)诜椒▋?nèi)部對(duì)該異常進(jìn)行捕獲,并未向上層拋出,我們期望的場(chǎng)景是兩次數(shù)據(jù)插入執(zhí)行失敗,但是觀察數(shù)據(jù)庫(kù)發(fā)現(xiàn),第一次數(shù)據(jù)庫(kù)插入操作已經(jīng)執(zhí)行成功,第二次數(shù)據(jù)插入執(zhí)行成功,與我們的預(yù)期結(jié)果不符,故而驗(yàn)證@Transactional注解在方法中異常被捕獲的場(chǎng)景中會(huì)失效;

究其原因:Spring的事務(wù)是在調(diào)用業(yè)務(wù)方法之前開(kāi)始的,業(yè)務(wù)方法執(zhí)行完畢之后才執(zhí)行commit 或 rollback,事務(wù)是否執(zhí)行取決于是否拋出runtime異常,如果拋出runtime exception并在你的業(yè)務(wù)方法中并沒(méi)有catch到的話,事務(wù)就會(huì)回滾。

三、“事務(wù)”知識(shí)回顧

1.什么是事務(wù)?

事務(wù)(Transaction)是由一系列對(duì)系統(tǒng)中數(shù)據(jù)進(jìn)行訪問(wèn)與更新的操作組成的一個(gè)程序執(zhí)行邏輯單元(Unit)。

通常我們所指的事務(wù)是指數(shù)據(jù)庫(kù)事務(wù),使用數(shù)據(jù)庫(kù)事務(wù)有以下兩處優(yōu)點(diǎn):

  • 當(dāng)多個(gè)應(yīng)用程序并發(fā)訪問(wèn)數(shù)據(jù)庫(kù)時(shí),事務(wù)可以在這些應(yīng)用程序之間提供一個(gè)隔離方法,以防止彼此的操作互相干擾。

  • 事務(wù)為數(shù)據(jù)庫(kù)操作序列提供了一個(gè)從失敗恢復(fù)到正常狀態(tài)的方法,同時(shí)提供了數(shù)據(jù)庫(kù)即使在異常狀態(tài)下仍能保持?jǐn)?shù)據(jù)一致性的方法。

2. 事務(wù)具有的特性?

原子性(Atomicity)、一致性(Consistency)、隔離性(Isolation)和持久性,簡(jiǎn)稱(chēng)事務(wù)的ACID特性。

  • 原子性

事務(wù)的原子性是指事務(wù)必須是一個(gè)原子的操作序列單元,即事務(wù)中包含的各項(xiàng)操作在一次執(zhí)行過(guò)程中只會(huì)出現(xiàn)兩種狀態(tài):全部成功執(zhí)行、全部不執(zhí)行。任何一項(xiàng)操作失敗都將導(dǎo)致整個(gè)事務(wù)失敗,同時(shí)其他已經(jīng)被執(zhí)行的操作都將被撤銷(xiāo)并回滾,只打所有的操作全部成功,整個(gè)事務(wù)才算是成功完成。

  • 一致性

事務(wù)的一致性是指事務(wù)的執(zhí)行不能破壞數(shù)據(jù)庫(kù)數(shù)據(jù)的完整性和一致性,一個(gè)事務(wù)在執(zhí)行之前和執(zhí)行之后,數(shù)據(jù)庫(kù)都必須處于一致性狀態(tài)。也就是說(shuō),事務(wù)執(zhí)行的結(jié)果必須是使數(shù)據(jù)庫(kù)從一個(gè)一致性狀態(tài)轉(zhuǎn)變到另一個(gè)一致性狀態(tài),因此當(dāng)數(shù)據(jù)庫(kù)只包含成功事務(wù)提交 的結(jié)果時(shí),就能說(shuō)數(shù)據(jù)庫(kù)處于一致性狀態(tài)。而如果數(shù)據(jù)庫(kù)系統(tǒng)在運(yùn)行過(guò)程中發(fā)生故障, 有些事務(wù)尚未完成就被迫中斷,這些未完成的事務(wù)對(duì)數(shù)據(jù)庫(kù)所做的修改有一部分已寫(xiě)入物理數(shù)據(jù)庫(kù),這時(shí)數(shù)據(jù)庫(kù)就處于一種不正確的狀態(tài),或者說(shuō)是不一致的狀態(tài)。

  • 隔離性

事務(wù)的隔離性是指在并發(fā)環(huán)境中,并發(fā)的事務(wù)是相互隔離的,一個(gè)事務(wù)的執(zhí)行不能被其他事務(wù)干擾。也就是說(shuō),不同的事務(wù)并發(fā)操縱相同的數(shù)據(jù)時(shí),每個(gè)事務(wù)都有各自完整的數(shù)據(jù)空間,即一個(gè)事務(wù)內(nèi)部的操作及使用的數(shù)據(jù)對(duì)其他并發(fā)事務(wù)是隔離的,并發(fā)執(zhí)行的 各個(gè)事務(wù)之間不能互相干擾。

  • 持久性

事務(wù)一旦提交,其所做的修改就會(huì)永久保存到數(shù)據(jù)庫(kù)中,即使數(shù)據(jù)庫(kù)發(fā)生故障也不應(yīng)該對(duì)其有任何影響。需要注意的是,事務(wù)的持久性不能做到100%的持久,只能從事務(wù)本身的角度來(lái)保證永久性,而一些外部原因?qū)е聰?shù)據(jù)庫(kù)發(fā)生故障,如硬盤(pán)損壞,那么所有提交的數(shù)據(jù)可能都會(huì)丟失。

3. 什么是Spring中的事務(wù)?

Spring中同樣提供了很好的事務(wù)管理機(jī)制,主要分為編程式事務(wù)聲明式事務(wù)。

  • 編程式事務(wù)

是指在代碼中手動(dòng)的管理事務(wù)的提交、回滾等操作,代碼侵入性比較強(qiáng)。編程式事務(wù)方式需要開(kāi)發(fā)者在代碼中手動(dòng)的管理事務(wù)的開(kāi)啟、提交、回滾等操作。

public void test() {
      TransactionDefinition def = new DefaultTransactionDefinition();
      TransactionStatus status = transactionManager.getTransaction(def);
      try {
         // 事務(wù)操作
         // 事務(wù)提交
         transactionManager.commit(status);
      } catch (DataAccessException e) {
         // 事務(wù)提交
         transactionManager.rollback(status);
         throw e;
      }
}
  • 聲明式事務(wù)

聲明式事務(wù)是基于AOP面向切面,它將具體業(yè)務(wù)和事務(wù)處理部分解耦,代碼侵入性很低,實(shí)際開(kāi)發(fā)中比較常用。我們常用TX和AOP的xml配置文件方式和@Transactional注解方式。

?聲明式事務(wù)的優(yōu)點(diǎn):

對(duì)代碼無(wú)侵入性,方法內(nèi)只需要寫(xiě)業(yè)務(wù)邏輯,節(jié)省很多代碼量。

?聲明式事務(wù)的缺點(diǎn):

1、聲明式事務(wù)粒度問(wèn)題:聲明式事務(wù)的局限就是最小粒度要作用在方法上,且不適合耗時(shí)長(zhǎng)、高并發(fā)場(chǎng)景。

2、聲明式事務(wù)容易被開(kāi)發(fā)者忽略,當(dāng)事務(wù)嵌套的方法中存在RPC遠(yuǎn)程調(diào)用、MQ發(fā)送、Redis更行、文件寫(xiě)入等操作可能存在以下場(chǎng)景:

? 事務(wù)嵌套的方法中RPC調(diào)用成功了,但是本地事務(wù)回滾導(dǎo)致RPC調(diào)用無(wú)法回滾(暫不討論分布式事務(wù))。

?事務(wù)嵌套的方法中遠(yuǎn)程調(diào)用會(huì)拉長(zhǎng)整個(gè)事務(wù)周期,導(dǎo)致事務(wù)的數(shù)據(jù)庫(kù)連接一致被占用,類(lèi)似操作過(guò)多會(huì)導(dǎo)致數(shù)據(jù)庫(kù)連接池耗盡。

3、聲明式事務(wù)使用錯(cuò)誤會(huì)導(dǎo)致在某些場(chǎng)景下失效。

四、總結(jié)

以上就是Spring注解@Transactional失效的場(chǎng)景分析的詳細(xì)內(nèi)容,更多關(guān)于Spring注解@Transactional失效的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • Springboot整合Redis的詳細(xì)教程分享

    Springboot整合Redis的詳細(xì)教程分享

    這篇文章主要為大家詳細(xì)介紹了如何利用SpringBoot整合Redis,文中的示例代碼講解詳細(xì),具有很好的參考價(jià)值,希望對(duì)大家有所幫助
    2022-08-08
  • Spring Boot整合MyBatis-Flex全過(guò)程

    Spring Boot整合MyBatis-Flex全過(guò)程

    這篇文章主要介紹了Spring Boot整合MyBatis-Flex全過(guò)程,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2024-08-08
  • Java遍歷起止日期中間的所有日期操作

    Java遍歷起止日期中間的所有日期操作

    這篇文章主要介紹了Java遍歷起止日期中間的所有日期操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2020-09-09
  • SpringBoot中的Redis?緩存問(wèn)題及操作方法

    SpringBoot中的Redis?緩存問(wèn)題及操作方法

    這篇文章主要介紹了SpringBoot中的Redis?緩存,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2022-10-10
  • Spring定時(shí)任務(wù)使用及如何使用郵件監(jiān)控服務(wù)器

    Spring定時(shí)任務(wù)使用及如何使用郵件監(jiān)控服務(wù)器

    這篇文章主要介紹了Spring定時(shí)任務(wù)使用及如何使用郵件監(jiān)控服務(wù)器,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2019-07-07
  • Mybatis分頁(yè)插件PageHelper的分頁(yè)原理剖析

    Mybatis分頁(yè)插件PageHelper的分頁(yè)原理剖析

    這篇文章主要介紹了Mybatis分頁(yè)插件PageHelper的分頁(yè)原理剖析,PageHelper作為一個(gè)啟動(dòng)器,那么就和其他啟動(dòng)器加載一樣,先讀取spring.factories文件里面配置的類(lèi),轉(zhuǎn)成Bean加載本系統(tǒng)中,然后執(zhí)行他的前置后置處理方法,完成初始化,需要的朋友可以參考下
    2023-08-08
  • IDEA 設(shè)置顯示內(nèi)存的使用情況和內(nèi)存回收的方法

    IDEA 設(shè)置顯示內(nèi)存的使用情況和內(nèi)存回收的方法

    這篇文章主要介紹了IDEA 設(shè)置顯示內(nèi)存的使用情況和內(nèi)存回收的方法,本文通過(guò)圖文并茂的形式給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-04-04
  • Mybatis 傳輸List的實(shí)現(xiàn)代碼

    Mybatis 傳輸List的實(shí)現(xiàn)代碼

    本文通過(guò)實(shí)例代碼給大家介紹了mybatis傳輸list的實(shí)現(xiàn)代碼,非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友參考下吧
    2017-09-09
  • Java中的static關(guān)鍵字深入理解

    Java中的static關(guān)鍵字深入理解

    這篇文章主要介紹了Java中的static關(guān)鍵字深入理解,文字和代碼列舉了實(shí)際例子,有感興趣的同學(xué)可以研究下
    2021-03-03
  • Java報(bào)錯(cuò):Java.io.FileNotFoundException解決方法

    Java報(bào)錯(cuò):Java.io.FileNotFoundException解決方法

    這篇文章主要介紹了Java.io.FileNotFoundException的產(chǎn)生原因和解決方法,造成這個(gè)報(bào)錯(cuò)的原因可能有文件路徑錯(cuò)誤、文件被刪除或移動(dòng)和權(quán)限問(wèn)題,文中將解決的辦法介紹的非常詳細(xì),需要的朋友可以參考下
    2024-12-12

最新評(píng)論