Spring的聲明式事務(wù)即使用@Transactional注解的方式來(lái)標(biāo)明該方法需要事務(wù)支持。
當(dāng)使用Spring的事務(wù)管理的時(shí)候,需要特別注意的是@Transactional注解來(lái)自org.springframework.transaction.annotation包而不是javax.transaction。Spring提供了一個(gè)EnableTransactionManagement注解配置在配置類上來(lái)開(kāi)啟聲明式事務(wù)的支持,使用了該注解后Spring會(huì)自動(dòng)掃描@Transactional追。
注解事務(wù)行為
事務(wù)的傳播行為
REQUIRED:表示業(yè)務(wù)方法需要在一個(gè)事務(wù)中處理,如果業(yè)務(wù)方法執(zhí)行時(shí)已經(jīng)在一個(gè)事務(wù)中,則加入該事務(wù),否則重新開(kāi)啟一個(gè)事務(wù)。這也是默認(rèn)的事務(wù)傳播行為;
NOT_SUPPORTED:聲明業(yè)務(wù)方法不需要事務(wù),如果業(yè)務(wù)方法執(zhí)行時(shí)已經(jīng)在一個(gè)事務(wù)中,則事務(wù)被掛起,等方法執(zhí)行完畢后,事務(wù)恢復(fù)進(jìn)行;
REQUIRES_NEW:表明業(yè)務(wù)方法需要在一個(gè)單獨(dú)的事務(wù)中進(jìn)行,如果業(yè)務(wù)方法進(jìn)行時(shí)已經(jīng)在一個(gè)事務(wù)中,則這個(gè)事務(wù)被掛起,并重新開(kāi)啟一個(gè)事務(wù)來(lái)執(zhí)行這個(gè)業(yè)務(wù)方法,業(yè)務(wù)方法執(zhí)行完畢后,原來(lái)的事務(wù)恢復(fù)進(jìn)行;
MANDATORY:該屬性指定業(yè)務(wù)方法只能在一個(gè)已經(jīng)存在的事務(wù)中進(jìn)行,業(yè)務(wù)方法不能發(fā)起自己的事務(wù);如果業(yè)務(wù)方法沒(méi)有在一個(gè)既有的事務(wù)中進(jìn)行,容器將拋出異常;
SUPPORTS:該屬性指定,如果業(yè)務(wù)方法在一個(gè)既有的事務(wù)中進(jìn)行,則加入該事務(wù);否則,業(yè)務(wù)方法將在一個(gè)沒(méi)有事務(wù)的環(huán)境下進(jìn)行;
NEVER:指定業(yè)務(wù)方法不可以在事務(wù)中進(jìn)行,如果業(yè)務(wù)方法執(zhí)行時(shí)已經(jīng)在一個(gè)事務(wù)中,容器將拋出異常;
NESTED:該屬性指定,如果業(yè)務(wù)方法在一個(gè)既有的事務(wù)中執(zhí)行,則該業(yè)務(wù)方法將在一個(gè)嵌套的事務(wù)中進(jìn)行;否則,按照REQUEIRED來(lái)對(duì)待。它使用一個(gè)單獨(dú)的事務(wù),這個(gè)事務(wù)可以有多個(gè)rollback點(diǎn),內(nèi)部事務(wù)的rollback對(duì)外部事務(wù)沒(méi)有影響,但外部事務(wù)的rollback會(huì)導(dǎo)致內(nèi)部事務(wù)的rollback。這個(gè)行為只對(duì)DataSourceTransactionManager有效。
事務(wù)的隔離級(jí)別
使用@Transactional的Isolation屬性可以指定事務(wù)的隔離級(jí)別。但事務(wù)的隔離級(jí)別是由底層的數(shù)據(jù)庫(kù)實(shí)現(xiàn)的,并不是由Spring來(lái)實(shí)現(xiàn)。
READ_UNCOMMITTED:會(huì)出現(xiàn)臟讀、不可重復(fù)讀和幻讀問(wèn)題;
READ_COMMITTED:會(huì)出現(xiàn)不可重復(fù)讀和幻讀問(wèn)題;
REPEATABLE_READ:會(huì)出現(xiàn)幻讀問(wèn)題;
-
SERIALIZABLE:串行化,不會(huì)出現(xiàn)上面的問(wèn)題。
一般的數(shù)據(jù)庫(kù)默認(rèn)提供的是READ_COMMITTED隔離級(jí)別,如sqlserver2000;Mysql默認(rèn)提供的是REPEATABLE_READ。
這里寫(xiě)圖片描述
默認(rèn)遇到運(yùn)行期例外(throw new RuntimeException("注釋");)會(huì)回滾,即遇到不受檢查(unchecked)的例外時(shí)回滾;
而遇到需要捕獲的例外(throw new Exception("注釋");)不會(huì)回滾,即遇到受檢查的例外(就是非運(yùn)行時(shí)拋出的異常,編譯器會(huì)檢查到的異常叫受檢查例外或說(shuō)受檢查異常)時(shí),需我們指定方式來(lái)讓事務(wù)回滾 ,如下:
@Transactional(rollbackFor=Exception.class) //指定回滾,遇到異常Exception時(shí)回滾
public void methodName() {
throw new Exception("注釋");
}
@Transactional(noRollbackFor=Exception.class)//指定不回滾,遇到運(yùn)行期例外(throw new RuntimeException("注釋");)會(huì)回滾
public ItimDaoImpl getItemDaoImpl() {
throw new RuntimeException("注釋");
}
類級(jí)別使用@Transactional
@Transactional不僅可以注解在方法上,也可以注解在類上,當(dāng)注解在類上的時(shí)候,表明此類的所有public方法都是開(kāi)啟事務(wù)的,如果類級(jí)別和方法級(jí)別同時(shí)使用了@Transactional注解,則使用在類級(jí)別的注解會(huì)重載方法級(jí)別的注解。在使用類級(jí)別注解的時(shí)候,推薦將類中的select查詢方法同時(shí)加上@Transactional(readOnly=true)屬性。
Spring Data JPA的事務(wù)支持
Spring Data JPA對(duì)所有默認(rèn)的方法都開(kāi)啟了事務(wù)支持,且對(duì)所有的查詢類事務(wù)默認(rèn)啟用readOnly=true屬性。這一點(diǎn)可以去看SimpleJpaRepository的源碼。的確如此。
Spring Boot的事務(wù)支持
自動(dòng)配置的事務(wù)管理器
在使用JDBC作為數(shù)據(jù)訪問(wèn)技術(shù)的時(shí)候,SpringBOOT為我們定義PlatformTransactionManager的實(shí)現(xiàn)DataSourceTransactionManager的Bean,配置見(jiàn)org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration.class類中的定義.
??在使用JPA作為數(shù)據(jù)訪問(wèn)的技術(shù)的時(shí)候,SpringBoot為我們定義了一個(gè)PlatformTransactionManager的實(shí)現(xiàn)JpaTransactionManager的Bean,配置見(jiàn)org.springframework.boot.autoconfigure.orm.jpa.JpaBaseConfiguration.class類中的定義
自動(dòng)開(kāi)啟注解事務(wù)的支持
Spring Boot專門(mén)用于配置事務(wù)的類為org.springframework.boot.autoconfigure.jdbc.transaction.TransactionAutoConfiguration,此配置類依賴于JpaBaseConfiguration和DataSourceTransactionManagerAutoConfiguration。而在DataSourceTransactionManagerAutoConfiguration配置里還開(kāi)啟了對(duì)聲明式事務(wù)的支持。所以在Spring Boot中無(wú)需顯示啟用@EnableTransactionManagement注解。