一、聲明式事務(wù)配置:
(一)申明式事務(wù)配置步驟:
????1、xml文件頭部需要添加spring的相關(guān)支持:

????2、配置事務(wù)管理器

? ? 3、配置需要加入事務(wù)的方法規(guī)則,或者說(shuō)是一個(gè)切面

(二)注解式事務(wù)配置
1、添加注解配置
<!-- 定義事務(wù)管理器 -->?
<bean id="transactionManager"? class="org.springframework.jdbc.datasource.DataSourceTransactionManager">?
? <property name="dataSource" ref="dataSource" />?
</bean>?
<!--使用注釋事務(wù) -->?
<tx:annotation-driven? transaction-manager="transactionManager" />
2、在需要加入事務(wù)的方法或者類上添加@Transactional
事物配置中有哪些屬性可以配置
(1)事務(wù)的傳播性:@Transactional(propagation=Propagation.REQUIRED)?
? ? ? 如果有事務(wù), 那么加入事務(wù), 沒(méi)有的話新建一個(gè)(默認(rèn)情況下)
(2)事務(wù)的超時(shí)性:@Transactional(timeout=30) //默認(rèn)是30秒?
? ? ? 注意這里說(shuō)的是事務(wù)的超時(shí)性而不是Connection的超時(shí)性,這兩個(gè)是有區(qū)別的
(3)事務(wù)的隔離級(jí)別:@Transactional(isolation = Isolation.READ_UNCOMMITTED)
? ? ? 讀取未提交數(shù)據(jù)(會(huì)出現(xiàn)臟讀, 不可重復(fù)讀) 基本不使用
(4)回滾:
指定單一異常類:@Transactional(rollbackFor=RuntimeException.class)
指定多個(gè)異常類:@Transactional(rollbackFor={RuntimeException.class, Exception.class})
該屬性用于設(shè)置需要進(jìn)行回滾的異常類數(shù)組,當(dāng)方法中拋出指定異常數(shù)組中的異常時(shí),則進(jìn)行事務(wù)回滾。
(5)只讀:@Transactional(readOnly=true)
該屬性用于設(shè)置當(dāng)前事務(wù)是否為只讀事務(wù),設(shè)置為true表示只讀,false則表示可讀寫(xiě),默認(rèn)值為false。
例如:
@Transactional(propagation=Propagation.REQUIRED,rollbackFor=Exception.class,timeout=1,isolation=Isolation.DEFAULT)?
public void saveUser(Map<String, String> map) throws Exception {?
? ? System.out.println("方法開(kāi)始");?
? ? for (int i = 0; i < 500000; i++) {?
? ? ? ? ? ? System.out.println("*");?
? ? ? ? }?
? ? System.out.println("進(jìn)入保存");?
? ? userDao.saveUser(map);?
? ? System.out.println("退出保存");?
}?
解釋說(shuō)明
事務(wù)的傳播級(jí)別定義的是事務(wù)的控制范圍,主要是父子事務(wù)之間的相互影響關(guān)系;事務(wù)的隔離級(jí)別定義的是事務(wù)讀寫(xiě)的控制范圍,主要是兩個(gè)事務(wù)之間的相互影響關(guān)系。
傳播級(jí)別:
1)、REQUIRED
如果當(dāng)前方法已經(jīng)在事務(wù)中,那么就以父事務(wù)執(zhí)行,不需要新建事務(wù);如果當(dāng)前方法不在事務(wù)中,那么就為當(dāng)前方法新建事務(wù)?;貪L情況:父子方法中任何地方出現(xiàn)問(wèn)題,都會(huì)全部回滾。
2)、SURPPORTED
如果當(dāng)前方法已經(jīng)在事務(wù)中,那么就以當(dāng)前事務(wù)執(zhí)行;如果當(dāng)前方法不再事務(wù)中,那么就以非事務(wù)方式運(yùn)行。如果運(yùn)行在事務(wù)中,那么只要出現(xiàn)異常都會(huì)回滾。
3)、NOT_SURPPORTED
如果當(dāng)前方法已經(jīng)在事務(wù)中,那么就掛起當(dāng)前事務(wù),以非事務(wù)方式運(yùn)行,方法執(zhí)行完畢后,恢復(fù)事務(wù);如果當(dāng)前方法不再事務(wù)中,那么就以非事務(wù)方式執(zhí)行。
4)、MANDATORY
強(qiáng)制以事務(wù)方式執(zhí)行,如果當(dāng)前方法不在事務(wù)中,那么會(huì)拋出異常。
5)、NEVER
與MANDATORY相反,強(qiáng)制以非事務(wù)方式執(zhí)行,如果當(dāng)前方法在事務(wù)中,那么會(huì)拋出異常。
6)、REQUIRED_NEW
與REQUIRED不同的是,無(wú)論該方法當(dāng)前是不是在事務(wù)中,都會(huì)為自己新建一個(gè)事務(wù)。如果當(dāng)前已經(jīng)在事務(wù)中,那么會(huì)掛起父事務(wù),為自己新建一個(gè)事務(wù)。父事務(wù)不影響它子事務(wù)的提交和回滾。
7)、NESTED
嵌套事務(wù)。理解Nested的關(guān)鍵是savepoint。他與PROPAGATION_REQUIRES_NEW的區(qū)別是,PROPAGATION_REQUIRES_NEW另起一個(gè)事務(wù),將會(huì)與他的父事務(wù)相互獨(dú)立,而Nested的事務(wù)和他的父事務(wù)是相依的,他的提交是要等和他的父事務(wù)一塊提交的。也就是說(shuō),如果父事務(wù)最后回滾,他也要回滾的。而Nested事務(wù)的好處是他有一個(gè)savepoint。
例如:
ServiceA {
/**
* 事務(wù)屬性配置為 PROPAGATION_REQUIRED
*/
void methodA() {
try {
//savepoint
ServiceB.methodB(); //PROPAGATION_NESTED 級(jí)別
} catch (SomeException) {
// 執(zhí)行其他業(yè)務(wù), 如 ServiceC.methodC();
}
}
}
也就是說(shuō)ServiceB.methodB失敗回滾,那么ServiceA.methodA也會(huì)回滾到savepoint點(diǎn)上,ServiceA.methodA可以選擇另外一個(gè)分支,比如ServiceC.methodC,繼續(xù)執(zhí)行,來(lái)嘗試完成自己的事務(wù)。
原文鏈接:https://blog.csdn.net/wgh1015398431/java/article/details/52861048