詳細談?wù)凷pring事務(wù)是如何管理的_第1頁
詳細談?wù)凷pring事務(wù)是如何管理的_第2頁
詳細談?wù)凷pring事務(wù)是如何管理的_第3頁
詳細談?wù)凷pring事務(wù)是如何管理的_第4頁
詳細談?wù)凷pring事務(wù)是如何管理的_第5頁
已閱讀5頁,還剩6頁未讀, 繼續(xù)免費閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認領(lǐng)

文檔簡介

第詳細談?wù)凷pring事務(wù)是如何管理的目錄前言Spring事務(wù)抽象PlatformTransactionManager是事務(wù)管理器接口常見的事務(wù)管理器有以下幾種定義事務(wù)的一些參數(shù):

7種事務(wù)傳播特性:

四種事務(wù)隔離級別:

Spring之編程式事務(wù)聲明式事務(wù)為什么加了@Transactional注解事物就生效了?通過注解怎么實現(xiàn)指定的傳播特性和隔離級別的?事務(wù)失效的8種情況及解決辦法總結(jié)

前言

我們都知道Spring給我們提供了很多抽象,比如我們在操作數(shù)據(jù)庫的過程中,它為我們提供了事務(wù)方面的抽象,讓我們可以非常方便的以事務(wù)方式操作數(shù)據(jù)庫。不管你用JDBC、Mybatis、Hibernate等任何一種方式操作數(shù)據(jù)庫,也不管你使用DataSource還是JTA的事務(wù),Spring事務(wù)抽象管理都能很好的把他統(tǒng)一在一起。接下來看一下事務(wù)的抽象核心接口

Spring事務(wù)抽象

PlatformTransactionManager是事務(wù)管理器接口

//事務(wù)管理器接口有以下幾個接口,獲取事務(wù)信息,提交和回滾

publicinterfacePlatformTransactionManager{

TransactionStatusgetTransaction(@NullableTransactionDefinitionvar1)throwsTransactionException;

voidcommit(TransactionStatusvar1)throwsTransactionException;

voidrollback(TransactionStatusvar1)throwsTransactionException;

}

常見的事務(wù)管理器有以下幾種

DataSourceTransactionManager

HibernateTransactionManager

JtaTransactionManager

這些管理器都實現(xiàn)了PlatformTransactionManager中的三個接口,實現(xiàn)邏輯略有差別,但是對用戶來講區(qū)別不大

定義事務(wù)的一些參數(shù):

一些事務(wù)的參數(shù)在TransactionDefinition.java中,詳情如下:

publicinterfaceTransactionDefinition{

intPROPAGATION_REQUIRED=0;

intPROPAGATION_SUPPORTS=1;

intPROPAGATION_MANDATORY=2;

intPROPAGATION_REQUIRES_NEW=3;

intPROPAGATION_NOT_SUPPORTED=4;

intPROPAGATION_NEVER=5;

intPROPAGATION_NESTED=6;

//默認隔離級別,和數(shù)據(jù)庫的隔離級別一致

intISOLATION_DEFAULT=-1;

intISOLATION_READ_UNCOMMITTED=1;

intISOLATION_READ_COMMITTED=2;

intISOLATION_REPEATABLE_READ=4;

intISOLATION_SERIALIZABLE=8;

//默認不超時

intTIMEOUT_DEFAULT=-1;

}

下面兩張圖對這些參數(shù)進行了說明:

7種事務(wù)傳播特性:

四種事務(wù)隔離級別:

在看事務(wù)隔離級別前需要先了解下什么是臟讀、不可重復(fù)讀、幻讀

臟讀:臟讀就是一個事物未提交的數(shù)據(jù),被另外一個事務(wù)讀到了,顯然這種情況不可接受

不可重復(fù)讀:不可重復(fù)讀是指在一個事務(wù)內(nèi),多次讀同一數(shù)據(jù),前后讀取的結(jié)果不一致。

幻讀:事務(wù)A對表中的一個數(shù)據(jù)進行了修改,這種修改涉及到表中的全部數(shù)據(jù)行。同時事務(wù)B也修改了這個表中的數(shù)據(jù),這種修改是向表中插入一行新數(shù)據(jù)。那么就會發(fā)生操作事務(wù)A的用戶發(fā)現(xiàn)表中還存在沒有修改的數(shù)據(jù)行,就好像發(fā)生了幻覺一樣

知道了以上幾個概念,我們來看看隔離級別:

這里我們可以看到,Spring并不是提供了所有的事務(wù)管理的實現(xiàn),而是提供了標準的事務(wù)管理器的操作接口PlatformTransactionManager,并且規(guī)范了其行為,具體的事務(wù)實現(xiàn)由各個平臺自行實現(xiàn)。這就是Spring的事務(wù)抽象。

Spring之編程式事務(wù)

Spring提供了TransactionTemplate工具類可以很方便的使用編程式事務(wù)。默認情況下TransactionTemplate使用的是DataSourceTransactionManager。

在Spring上下文中,我們不配置TransactionTemplate這個bean,也能獲取到TransactionTemplate。比如下面的例子。

@Service

publicclassUserInfoService{

@Resource

privateUserInfoDAOuserInfoDAO;

@Autowired

privateTransactionTemplatetransactionTemplate;

publicvoidupdateUser1(){

transactionTemplate.execute(transactionStatus-{

userInfoDAO.updateUserName(1,"zhangsanfeng");

transactionTemplate.execute(transactionStatus2-{

userInfoDAO.updateUserName(2,"lisi");

returnnull;

returnnull;

}

由于Spring默認的事務(wù)傳播特性是PROPAGATION_REQUIRED,我們來做一下驗證,看是不是這樣

上面兩幅圖可以看出,TransactionStatus中的newTransaction屬性,第一個是true,第二個是false,正好符合PROPAGATION_REQUIRED所描述的情況。其他的傳播特性可以自己去驗證。

聲明式事務(wù)

除了編程式事務(wù)外,Spring還為我們提供了聲明式事務(wù)。使用@Transactional注解。

@Transactional可以作用于接口、接口方法、類以及類方法上。當(dāng)作用于類上時,該類的所有public方法將都具有該類型的事務(wù)屬性,同時,我們也可以在方法級別使用該注解來覆蓋類級別的定義。

雖然@Transactional注解可以作用于接口、接口方法、類以及類方法上,但是Spring建議不要在接口或者接口方法上使用該注解,因為這只有在使用基于接口的代理時它才會生效。另外,@Transactional注解應(yīng)該只被應(yīng)用到public方法上,這是由SpringAOP的本質(zhì)決定的。如果你在protected、private或者默認可見性的方法上使用@Transactional注解,這將被忽略,也不會拋出任何異常。

@Transactional的rollbackFor屬性可以設(shè)置一個Throwable的數(shù)組,用來表明如果方法拋出這些異常,則進行事務(wù)回滾。默認情況下如果不配置rollbackFor屬性,那么事務(wù)只會在遇到RuntimeException的時候才會回滾。

下面的代碼事務(wù)就不會生效:

@Transactional

publicvoidupdateUser2()throwsException{

intr1=userInfoDAO.updateUserName(1,"wanger");

intr2=userInfoDAO.updateUserName(2,"mawu");

if(r2==1){

thrownewException();

}

如果我們把拋出的異常改成RuntimeException,這時候事務(wù)就會生效了?;蛘咧付ó惓W屖聞?wù)生效,比如@Transactional(rollbackFor=Exception.class),這樣碰到所有的異常事務(wù)都會生效了。

為什么加了@Transactional注解事物就生效了?

這是因為Spring容器會為加了這個注解的對象生成一個代理對象,實際調(diào)用的時候,實際上是調(diào)用的代理對象。代理對象的實現(xiàn)了AOP的增強,實現(xiàn)了事務(wù)的實現(xiàn)。

通過注解怎么實現(xiàn)指定的傳播特性和隔離級別的?

public@interfaceTransactional{

@AliasFor("transactionManager")

Stringvalue()default"";

@AliasFor("value")

StringtransactionManager()default"";

String[]label()default{};

Propagationpropagation()defaultPropagation.REQUIRED;

Isolationisolation()defaultIsolation.DEFAULT;

inttimeout()default-1;

StringtimeoutString()default"";

booleanreadOnly()defaultfalse;

ClassextendsThrowable[]rollbackFor()default{};

String[]rollbackForClassName()default{};

ClassextendsThrowable[]noRollbackFor()default{};

String[]noRollbackForClassName()default{};

}

代碼中可以看出,我們可以指定隔離級別和傳播特性,在Spring為我們生成代理類的時候,會讀取這些屬性,體現(xiàn)在增強邏輯中。

事務(wù)失效的8種情況及解決辦法

數(shù)據(jù)庫引擎不支持事務(wù)

這里以MySQL為例,其MyISAM引擎是不支持事務(wù)操作的,InnoDB才是支持事務(wù)的引擎,一般要支持事務(wù)都會使用InnoDB,這時候選擇支持事務(wù)的數(shù)據(jù)庫即可(好像是廢話,哈哈哈)

沒有被Spring管理

這個好像沒什么可說的,脫離了Spring的管理,還談什么Spring事務(wù)管理。

方法不是public的

@Transactional只能用于public的方法上,否則事務(wù)不會失效,如果要用在非public方法上,可以開啟AspectJ代理模式。

數(shù)據(jù)源沒有配置事務(wù)管理器

相當(dāng)于沒開啟事務(wù)管理,如果不是Springboot情況需要進行如下操作。

@Bean

publicPlatformTransactionManagertransactionManager(DataSourcedataSource){

returnnewDataSourceTransactionManager(dataSource);

}

如果是SpringBoot,在啟動類上直接加上注解@EnableTransactionManagement即可。

傳播特性配錯了

傳播特性配置成,Propagation.SUPPORTED或者Propagation.NOT_SUPPORTED,改成支持事務(wù)的傳播特性即可。

異常類型錯誤

因為默認的異常類型是運行時異常,如果拋出了其他異常就不生效。

解決方式:

1、將異常改成運行時異常

2、指定異常進行事務(wù)回滾,如:@Transactional(rollbackFor=Exception.class)

異常被吃掉了

如果你代碼這么寫,事務(wù)不生效:

@Transactional(rollbackFor=Exception.class)

publicvoidupdateUser2(){

intr1=userInfoDAO.updateUserName(1,"3");

intr2=userInfoDAO.updateUserName(2,"4");

if(r2==1){

thrownewRuntimeException();

try{

}catch(Exceptione){

}

解決辦法:必須要拋出異常,否則Spring事務(wù)管理,不會走到回滾邏輯

類內(nèi)部調(diào)用

@Service

publicclassUserInfoService{

publicvoidjustUpdate(){

updateUser2();

@Transactional(rollbackFor=Exception.class)

publicvoidupdateUser2(){

}

上述代碼不生效,因為內(nèi)部調(diào)用不會涉及到代理類的調(diào)用,更不會有AOP的增強,因此不會生效。

解決辦法:

1、自注入

@Service

publicclassUserInfoService{

@Autowired

privateUserInfoServiceuserInfoService;

publicvoidjustUpdate(){

userInfoService.updateUser2();

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論