




版權(quán)說(shuō)明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡(jiǎn)介
理解Spring中的事務(wù)管理Spring事務(wù)的基本原理Spring事務(wù)的本質(zhì)其實(shí)就是數(shù)據(jù)庫(kù)對(duì)事務(wù)的?持,沒(méi)有數(shù)據(jù)庫(kù)的事務(wù)?持,Spring是?法提供事務(wù)功能的。對(duì)于純JDBC操作數(shù)據(jù)庫(kù),想要?到事務(wù),可以按照以下步驟進(jìn)?:1.獲取連接Connectioncon=DriverManager.getConnection()2.開(kāi)啟事務(wù)con.setAutoCommit(true/false);3.執(zhí)?CRUD4.提交事務(wù)/回滾事務(wù)mit()/con.rollback();5.關(guān)閉連接conn.close();使?Spring的事務(wù)管理功能后,我們可以不再寫(xiě)步驟2和4的代碼,?是由Spirng?動(dòng)完成。那么Spring是如何在我們書(shū)寫(xiě)的CRUD之前和之后開(kāi)啟事務(wù)和關(guān)閉事務(wù)的呢?解決這個(gè)問(wèn)題,也就可以從整體上理解Spring的事務(wù)管理實(shí)現(xiàn)原理了。下?簡(jiǎn)單地介紹下,注解?式為例?。1.配置?件開(kāi)啟注解驅(qū)動(dòng),在相關(guān)的類和?法上通過(guò)注解@Transactional標(biāo)識(shí)。2.spring在啟動(dòng)的時(shí)候會(huì)去解析?成相關(guān)的bean,這時(shí)候會(huì)查看擁有相關(guān)注解的類和?法,并且為這些類和?法?成代理,并根據(jù)@Transaction的相關(guān)參數(shù)進(jìn)?相關(guān)配置注?,這樣就在代理中為我們把相關(guān)的事務(wù)處理掉了(開(kāi)啟正常提交事務(wù),異常回滾事務(wù))。3.真正的數(shù)據(jù)庫(kù)層的事務(wù)提交和回滾是通過(guò)binlog或者redolog實(shí)現(xiàn)的。Spring的事務(wù)機(jī)制所有的數(shù)據(jù)訪問(wèn)技術(shù)都有事務(wù)處理機(jī)制,這些技術(shù)提供了API?來(lái)開(kāi)啟事務(wù)、提交事務(wù)來(lái)完成數(shù)據(jù)操作,或者在發(fā)?錯(cuò)誤的時(shí)候回滾數(shù)據(jù)。?Spring的事務(wù)機(jī)制是?統(tǒng)?的機(jī)制來(lái)處理不同數(shù)據(jù)訪問(wèn)技術(shù)的事務(wù)處理。Spring的事務(wù)機(jī)制提供了?個(gè)PlatformTransactionManager接?,不同的數(shù)據(jù)訪問(wèn)技術(shù)的事務(wù)使?不同的接?實(shí)現(xiàn),如表所?。數(shù)據(jù)訪問(wèn)技術(shù)及實(shí)現(xiàn)數(shù)據(jù)訪問(wèn)技術(shù)JDBC實(shí)現(xiàn)DataSourceTransactionManagerJapTransactionManagerHibernateTransactionManagerJdoTransactionManagerJtaTransactionManagerJPAHibernateJDO分布式事務(wù)在程序中定義事務(wù)管理器的代碼如下:@Bean(name="xxxTransactionManager")publicPlatformTransactionManagertransactionManager(){JpaTransactionManagertransactionManager=newJpaTransactionManager();transactionManager.setDataSource(dataSource());returntransactionManager;}聲名式事務(wù)Spring?持聲名式事務(wù),即使?注解來(lái)選擇需要使?事務(wù)的?法,它使?@Transactional注解在?法上表明該?法需要事務(wù)?持。@TransactionalpublicvoidupdateName(Longid,Stringname){//數(shù)據(jù)庫(kù)操作}在此處需要特別注意的是,此@Transactional注解來(lái)?org.springframework.transaction.annotation包,?不是javax.transaction。Spring的聲明式事務(wù)管理是建?在SpringAOP機(jī)制之上的,其本質(zhì)是對(duì)?標(biāo)?法前后進(jìn)?攔截,并在?標(biāo)?法開(kāi)始之前創(chuàng)建或者加??個(gè)事務(wù),在執(zhí)?完?標(biāo)?法之后根據(jù)執(zhí)?情況提交或者回滾事務(wù)。即向業(yè)務(wù)組件中的?標(biāo)業(yè)務(wù)?法插?事務(wù)增強(qiáng)處理并?成相應(yīng)的代理對(duì)象供應(yīng)?程序(客戶端)使?從?達(dá)到?污染地添加事務(wù)的?的。聲明式事務(wù)最?的優(yōu)點(diǎn)就是不需要通過(guò)編程的?式管理事務(wù),這樣就不需要在業(yè)務(wù)邏輯代碼中摻雜事務(wù)管理的代碼,只需通過(guò)注解標(biāo)明的?式(或者在配置?件中作相關(guān)的事務(wù)規(guī)則聲明),便可以將事務(wù)規(guī)則應(yīng)?到業(yè)務(wù)邏輯中??偟膩?lái)說(shuō),聲明式事務(wù)得益于SpringIoC容器和SpringAOP機(jī)制的?持:IoC容器為聲明式事務(wù)管理提供了基礎(chǔ)設(shè)施,使得Bean對(duì)于Spring框架??是可管理的;?由于事務(wù)管理本?就是?個(gè)典型的橫切邏輯(正是AOP的?武之地),因此SpringAOP機(jī)制是聲明式事務(wù)管理的直接實(shí)現(xiàn)者。通過(guò)SpringAOP,其實(shí)現(xiàn)了在?法調(diào)?前、調(diào)?后插??些業(yè)務(wù)邏輯的?的。我們來(lái)看?下下?這個(gè)圖:上圖顯?,當(dāng)客戶端Callingcode調(diào)??個(gè)普通類PlainObject的foo()?法的時(shí)候,是直接作?在POJO類??對(duì)象上的,客戶端擁有的是被調(diào)?者的直接的引?。?使?了SpringAOP的動(dòng)態(tài)代理技術(shù)后,即當(dāng)客戶端嘗試調(diào)?POJO的foo()?法的時(shí)候,給他的不是POJO??的引?,?是?個(gè)動(dòng)態(tài)?成的代理類。如上圖所?,這個(gè)時(shí)候,實(shí)際客戶端擁有的是?個(gè)代理的引?,那么在調(diào)?foo()?法的時(shí)候,會(huì)?先調(diào)?Proxy的foo()?法,這個(gè)時(shí)候Proxy可以整體控制實(shí)際的POJO.foo()?法的?參和返回值,?如在調(diào)?前及調(diào)?后打印?志,都是可以輕松做到的。Spring中關(guān)于事務(wù)的配置總是由三個(gè)部分組成,即:DataSource、TransactionManager和代理機(jī)制三部分,?論哪種配置?式,?般變化的只是代理機(jī)制這部分。其中,DataSource、TransactionManager這兩部分只是會(huì)根據(jù)數(shù)據(jù)訪問(wèn)?式有所變化,?如使?hibernate進(jìn)?數(shù)據(jù)訪問(wèn)時(shí),DataSource實(shí)際為SessionFactory,TransactionManager的實(shí)現(xiàn)為HibernateTransactionManager。如下圖所?:兩種動(dòng)態(tài)代理實(shí)現(xiàn)AOPJDK代理的是接?,私有?法必然不會(huì)存在在接??,所以就不會(huì)被攔截到;CgLib代理的是類,private的?法照樣不會(huì)出現(xiàn)在?類?,也不能被攔截。JDK的動(dòng)態(tài)代理,具體有如下四步驟:通過(guò)實(shí)現(xiàn)InvocationHandler接?創(chuàng)建??的調(diào)?處理器;通過(guò)為Proxy類指定ClassLoader對(duì)象和?組interface來(lái)?成動(dòng)態(tài)代理類,這?是動(dòng)態(tài)?成了代理類的字節(jié)碼;通過(guò)反射機(jī)制獲得動(dòng)態(tài)代理類的構(gòu)造函數(shù),其唯?參數(shù)類型是調(diào)?處理器接?類型;通過(guò)構(gòu)造函數(shù)創(chuàng)建動(dòng)態(tài)代理類實(shí)例,構(gòu)造時(shí)調(diào)?處理器對(duì)象作為參數(shù)被傳?。CgLib(CodeGenerationLibrary)是?個(gè)強(qiáng)?的、?性能、?質(zhì)量的Code?成庫(kù),它可以在運(yùn)?期擴(kuò)展Java類與實(shí)現(xiàn)Java接?。Cglib封裝了ASM,可以在運(yùn)?期動(dòng)態(tài)?成新的class(?類)Cglib?于AOP,jdk中的proxy必須基于接?,Cglib卻沒(méi)有這個(gè)限制JDK代理與Cglib的原理區(qū)別Java動(dòng)態(tài)代理是利?反射機(jī)制?成?個(gè)實(shí)現(xiàn)代理接?的匿名類,在調(diào)?具體?法前調(diào)?InvokeHandler來(lái)處理。?cglib動(dòng)態(tài)代理是利?asm開(kāi)源包,將要代理的對(duì)象類的class?件加載進(jìn)來(lái),通過(guò)修改其字節(jié)碼?成?類來(lái)處理。1.如果?標(biāo)對(duì)象實(shí)現(xiàn)了接?,默認(rèn)情況下會(huì)采?JDK的動(dòng)態(tài)代理實(shí)現(xiàn)AOP2.如果?標(biāo)對(duì)象實(shí)現(xiàn)了接?,可以強(qiáng)制使?CGLIB實(shí)現(xiàn)AOP3.如果?標(biāo)對(duì)象沒(méi)有實(shí)現(xiàn)了接?,必須采?CGLIB庫(kù),Spring會(huì)?動(dòng)在JDK動(dòng)態(tài)代理和CGLIB之間轉(zhuǎn)換如果是類內(nèi)部?法?不了代理,這個(gè)時(shí)候可以通過(guò)維護(hù)?個(gè)??實(shí)例的代理。@ServicepublicclassPersonServiceImplimplementsPersonService{@AutowiredPersonRepositorypersonRepository;//注???代理對(duì)象,在本類內(nèi)部?法調(diào)?事務(wù)的傳遞性才會(huì)?效@AutowiredPersonServiceselfProxyPersonService;/***測(cè)試事務(wù)的傳遞性**@paramperson*@return*/@TransactionalpublicPersonsave(Personperson){Personp=personRepository.save(person);try{//新開(kāi)事務(wù)獨(dú)?回滾selfProxyPersonService.delete();}catch(Exceptione){e.printStackTrace();}try{//使?當(dāng)前事務(wù)全部回滾selfProxyPersonService.save2(person);}catch(Exceptione){e.printStackTrace();}personRepository.save(person);returnp;}@Transactionalpublicvoidsave2(Personperson){personRepository.save(person);thrownewRuntimeException();}@Transactional(propagation=Propagation.REQUIRES_NEW)publicvoiddelete(){personRepository.delete(1L);thrownewRuntimeException();}}Spring事務(wù)的傳播屬性所謂spring事務(wù)的傳播屬性,就是定義在存在多個(gè)事務(wù)同時(shí)存在的時(shí)候,spring應(yīng)該如何處理這些事務(wù)的?為。這些屬性在TransactionDefinition中定義,具體常量的解釋見(jiàn)下表:Propagation.NESTED(nested嵌套事務(wù)):如果當(dāng)前存在事務(wù),則嵌套在當(dāng)前事務(wù)中。如果當(dāng)前沒(méi)有事務(wù),則新建?個(gè)事務(wù)??執(zhí)?(和required?樣)。嵌套的事務(wù)使?保存點(diǎn)作為回滾點(diǎn),當(dāng)內(nèi)部事務(wù)回滾時(shí)不會(huì)影響外部事物的提交;但是外部回滾會(huì)把內(nèi)部事務(wù)?起回滾回去(這是和新建?個(gè)事務(wù)的區(qū)別)。Spring中事務(wù)隔離級(jí)別?先要了解?下數(shù)據(jù)庫(kù)的事務(wù)隔離級(jí)別臟讀:?事務(wù)對(duì)數(shù)據(jù)進(jìn)?了增刪改,但未提交,另?事務(wù)可以讀取到未提交的數(shù)據(jù)。如果第?個(gè)事務(wù)這時(shí)候回滾了,那么第?個(gè)事務(wù)就讀到了臟數(shù)據(jù)。不可重復(fù)讀:?個(gè)事務(wù)中發(fā)?了兩次讀操作,第?次讀操作和第?次操作之間,另外?個(gè)事務(wù)對(duì)數(shù)據(jù)進(jìn)?了修改,這時(shí)候兩次讀取的數(shù)據(jù)是不?致的?;米x:第?個(gè)事務(wù)查詢?定范圍內(nèi)的數(shù)據(jù),第?個(gè)事務(wù)在這個(gè)范圍insert?條數(shù)據(jù),這時(shí)候第?個(gè)事務(wù)會(huì)出現(xiàn)兩次查詢結(jié)果不?致的情況。總結(jié):隔離級(jí)別越?,越能保證數(shù)據(jù)的完整性和?致性,但是對(duì)并發(fā)性能的影響也越??多數(shù)的數(shù)據(jù)庫(kù)默認(rèn)隔離級(jí)別為ReadCommited,?如SqlServer、Oracle少數(shù)數(shù)據(jù)庫(kù)默認(rèn)隔離級(jí)別為:RepeatableRead如MySQL的InnoDB引擎(值得注意的是MySQLInnoDB引擎下的RR隔離級(jí)別已經(jīng)通過(guò)next-keylock解決了幻讀問(wèn)題)Spring中的事務(wù)隔離級(jí)別@Transactional注解中可以設(shè)置事務(wù)的隔離級(jí)別,默認(rèn)是ISOLATION_DEFAULT級(jí)別。由屬性接?TransactionDefinition可以看到,可返回四個(gè)基本事務(wù)屬性:publicinterfaceTransactionDefinition{intgetPropagationBehavior();//傳播?為。intgetIsolationLevel();//隔離級(jí)別。事務(wù)管理器根據(jù)它來(lái)控制另外?個(gè)事務(wù)可以看到本事務(wù)內(nèi)的哪些數(shù)據(jù)。intgetTimeout();//事務(wù)必須在多少秒內(nèi)完成。booleanisReadOnly();//事務(wù)是否只讀。事務(wù)管理器能夠根據(jù)這個(gè)返回值進(jìn)?優(yōu)化,確保事務(wù)是只讀的}事務(wù)的嵌套通過(guò)上?的理論知識(shí)的鋪墊,我們?致知道了數(shù)據(jù)庫(kù)事務(wù)和spring事務(wù)的?些屬性和特點(diǎn),接下來(lái)我們通過(guò)分析?些嵌套事務(wù)的場(chǎng)景,來(lái)深?理解spring事務(wù)傳播的機(jī)制。假設(shè)外層事務(wù)ServiceA的MethodA()調(diào)?內(nèi)層ServiceB的MethodB()PROPAGATION_REQUIRED(Spring默認(rèn))如果ServiceB.methodB()的事務(wù)級(jí)別定義為PROPAGATION_REQUIRED,那么執(zhí)?ServiceA.methodA()的時(shí)候Spring已經(jīng)起了事務(wù),這時(shí)調(diào)?ServiceB.methodB(),ServiceB.methodB()看到??已經(jīng)運(yùn)?在ServiceA.methodA()的事務(wù)內(nèi)部,就不再起新的事務(wù)。假如ServiceB.methodB()運(yùn)?的時(shí)候發(fā)現(xiàn)??沒(méi)有在事務(wù)中,他就會(huì)為??分配?個(gè)事務(wù)。這樣,在ServiceA.methodA()或者在ServiceB.methodB()內(nèi)的任何地?出現(xiàn)異常,事務(wù)都會(huì)被回滾。PROPAGATION_REQUIRES_NEW?如我們?cè)O(shè)計(jì)ServiceA.methodA()的事務(wù)級(jí)別為PROPAGATION_REQUIRED,ServiceB.methodB()的事務(wù)級(jí)別為PROPAGATION_REQUIRES_NEW。那么當(dāng)執(zhí)?到ServiceB.methodB()的時(shí)候,ServiceA.methodA()所在的事務(wù)就會(huì)掛起,ServiceB.methodB()會(huì)起?個(gè)新的事務(wù),等待ServiceB.methodB()的事務(wù)完成以后,它才繼續(xù)執(zhí)?。它與PROPAGATION_REQUIRED的事務(wù)區(qū)別在于事務(wù)的回滾程度了。因?yàn)镾erviceB.methodB()是新起?個(gè)事務(wù),那么就是存在兩個(gè)不同的事務(wù)。如果ServiceB.methodB()已經(jīng)提交,那么ServiceA.methodA()失敗回滾,ServiceB.methodB()是不會(huì)回滾的。如果ServiceB.methodB()失敗回滾,如果他拋出的異常被ServiceA.methodA()捕獲,ServiceA.methodA()事務(wù)仍然可能提交(主要看B拋出的異常是不是A會(huì)回滾的異常)。PROPAGATION_SUPPORTS假設(shè)ServiceB.methodB()的事務(wù)級(jí)別為PROPAGATION_SUPPORTS,那么當(dāng)執(zhí)?到ServiceB.methodB()時(shí),如果發(fā)現(xiàn)ServiceA.methodA()已經(jīng)開(kāi)啟了?個(gè)事務(wù),則加?當(dāng)前的事務(wù),如果發(fā)現(xiàn)ServiceA.methodA()沒(méi)有開(kāi)啟事務(wù),則??也不開(kāi)啟事務(wù)。這種時(shí)候,內(nèi)部?法的事務(wù)性完全依賴于最外層的事務(wù)。PROPAGATION_NESTED現(xiàn)在的情況就變得?較復(fù)雜了,ServiceB.methodB()的事務(wù)屬性被配置為PROPAGATION_NESTED,此時(shí)兩者之間?將如何協(xié)作呢?ServiceB#methodB如果rollback,那么內(nèi)部事務(wù)(即ServiceB#methodB)將回滾到它執(zhí)?前的SavePoint?外部事務(wù)(
溫馨提示
- 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 豬羊養(yǎng)殖知識(shí)培訓(xùn)課件
- 2025重慶涪陵“才聚涪州·引雁回巢”引才專項(xiàng)招聘410人(第一批)筆試參考題庫(kù)附帶答案詳解
- 2025福建福州左臺(tái)置業(yè)有限公司項(xiàng)目建設(shè)合同制人員招聘33人筆試參考題庫(kù)附帶答案詳解
- 2025浙江省安全生產(chǎn)科學(xué)研究有限公司招聘15人筆試參考題庫(kù)附帶答案詳解
- 2025建信人壽保險(xiǎn)股份有限公司濱州中心支公司招聘9人筆試參考題庫(kù)附帶答案詳解
- 角膜及眼表疾病知到智慧樹(shù)章節(jié)測(cè)試課后答案2024年秋溫州醫(yī)科大學(xué)
- 2025年河北石家莊印鈔有限公司招聘13人筆試參考題庫(kù)附帶答案詳解
- 2025年安徽三洲水利建設(shè)有限公司工作人員招聘9人筆試參考題庫(kù)附帶答案詳解
- 2025年中國(guó)人壽招聘筆試筆試參考題庫(kù)附帶答案詳解
- 2025山東省聯(lián)合農(nóng)藥工業(yè)有限公司招聘102人筆試參考題庫(kù)附帶答案詳解
- 2025年哈爾濱幼兒師范高等??茖W(xué)校單招職業(yè)技能測(cè)試題庫(kù)完整
- 做最勇敢的自己
- 小學(xué)數(shù)學(xué)中巧用信息技術(shù)創(chuàng)造情境教學(xué)
- 安徽省歷年中考語(yǔ)文現(xiàn)代文閱讀之非連續(xù)性文本閱讀6篇(截至2024年)
- 公司員工生日會(huì)活動(dòng)復(fù)盤(pán)
- 2025年北京青年政治學(xué)院高職單招高職單招英語(yǔ)2016-2024年參考題庫(kù)含答案解析
- 永輝超市存貨管理問(wèn)題及優(yōu)化建議9700字
- 大模型落地應(yīng)用實(shí)踐方案
- 售后服務(wù)組織結(jié)構(gòu)及崗位職責(zé)
- 2025年鞍鋼集團(tuán)招聘筆試參考題庫(kù)含答案解析
- 人文社科類橫向課題技術(shù)服務(wù)合同5篇
評(píng)論
0/150
提交評(píng)論