javascript
Spring实战(十三)Spring事务
1、什么是事務(wù)(Transaction)?
? ? ? ?事務(wù)是指邏輯上的一組操作,要么全部成功,要么全部失敗。
事務(wù)是指將一系列數(shù)據(jù)操作捆綁成為一個(gè)整體進(jìn)行統(tǒng)一管理。如果某一事務(wù)執(zhí)行成功,則該事務(wù)中進(jìn)行的所有數(shù)據(jù)更改均會(huì)提交,成為數(shù)據(jù)庫中的永久組成部分。如果事務(wù)執(zhí)行時(shí)遇到錯(cuò)誤必須取消或者回滾,則數(shù)據(jù)將全部恢復(fù)到操作前的狀態(tài),所有的數(shù)據(jù)的更改均被消除。
2.事務(wù)的特性
原子性:事務(wù)是一個(gè)不可分割的工作單位,事務(wù)中的操作要么都發(fā)生,要么都不發(fā)生。
一致性:事務(wù)前后的數(shù)據(jù)的完整性必須保持一致。
隔離性:多個(gè)用戶并發(fā)訪問數(shù)據(jù)庫,一個(gè)用戶的事務(wù)的執(zhí)行不能被其他事務(wù)干擾,多個(gè)并發(fā)事務(wù)之間的數(shù)據(jù)要相互隔離。
持續(xù)性:一個(gè)事務(wù)一旦提交,它對(duì)數(shù)據(jù)庫中數(shù)據(jù)的改變就應(yīng)該是永久性的,即使數(shù)據(jù)庫發(fā)生故障也不應(yīng)該有任何影響。
3.事務(wù)并發(fā)操作帶來哪些問題?
? ? ?丟失修改:兩個(gè)事務(wù)T1和T2讀入同一個(gè)數(shù)據(jù)并修改,T2提交的結(jié)果破壞了T1提交的結(jié)果,導(dǎo)致T1的修改被丟失。
臟讀:一個(gè)事務(wù)讀取了另一個(gè)事務(wù)改寫但還未提交的數(shù)據(jù),若這些事務(wù)被回滾,這個(gè)讀取就是無效的。
不可重復(fù)讀:在同一事務(wù)中,多次讀取同一數(shù)據(jù)返回的結(jié)果有所不同(讀時(shí)數(shù)據(jù)發(fā)生了改變)。
幻讀:一個(gè)事務(wù)讀取了幾行記錄后,另一個(gè)事務(wù)插入一些記錄,發(fā)生幻讀。后來的查詢中,第一個(gè)事務(wù)發(fā)現(xiàn)一些原來沒有的記錄。
?
4、Spring事務(wù)管理API(主要有3個(gè))
PlatformTransactionManager:事務(wù)管理器;
TransactionDefinition:事務(wù)的定義信息(隔離,傳播,超時(shí),只讀);
TransactionStatus:保存事務(wù)具體運(yùn)作狀態(tài)
?
5、PlatformTransactionManager 事務(wù)管理器
spring為不同的持久化框架提供了不同的PlatformTransactionManager。
不論 采用何種方式,都必須先創(chuàng)建“事務(wù)管理器”的對(duì)象。
?
6、TransactionDefinition 定義事務(wù)(隔離,傳播,超時(shí),只讀)
設(shè)置隔離級(jí)別:(一組常量定義)
(mysql 默認(rèn)REPEATABLE_READ、oracle默認(rèn) READ_COMMITTED)
?
定義事務(wù)的傳播行為
應(yīng)用場景:當(dāng)我們調(diào)用一個(gè)基于Spring的Service接口方法(如UserService#addUser())時(shí),它將運(yùn)行于Spring管理的事務(wù)環(huán)境中,Service接口方法可能會(huì)在內(nèi)部調(diào)用其它的Service接口方法以共同完成一個(gè)完整的業(yè)務(wù)操作,因此就會(huì)產(chǎn)生服務(wù)接口方法嵌套調(diào)用的情況, Spring通過事務(wù)傳播行為控制當(dāng)前的事務(wù)如何傳播到被嵌套調(diào)用的目標(biāo)服務(wù)接口方法中。
Spring在TransactionDefinition接口中規(guī)定了7種類型的事務(wù)傳播行為,它們規(guī)定了事務(wù)方法和事務(wù)方法發(fā)生嵌套調(diào)用時(shí)事務(wù)如何進(jìn)行傳播:
(當(dāng)使用PROPAGATION_NESTED時(shí),底層的數(shù)據(jù)源必須基于JDBC 3.0,并且實(shí)現(xiàn)者需要支持保存點(diǎn)事務(wù)機(jī)制。)
| 事務(wù)傳播行為類型 ???????????????????????? | ???????????????????????? 說明 ???????????????????????? |
| ???????????????????????? PROPAGATION_REQUIRED ???????????????????????? | ???????????????????????? 如果當(dāng)前沒有事務(wù),就新建一個(gè)事務(wù),如果已經(jīng)存在一個(gè)事務(wù)中,加入到這個(gè)事務(wù)中。這是最常見的選擇。 ???????????????????????? |
| ???????????????????????? PROPAGATION_SUPPORTS ???????????????????????? | ???????????????????????? 支持當(dāng)前事務(wù),如果當(dāng)前沒有事務(wù),就以非事務(wù)方式執(zhí)行。 ???????????????????????? |
| ???????????????????????? PROPAGATION_MANDATORY ???????????????????????? | ???????????????????????? 使用當(dāng)前的事務(wù),如果當(dāng)前沒有事務(wù),就拋出異常。 ???????????????????????? |
| ???????????????????????? PROPAGATION_REQUIRES_NEW ???????????????????????? | ???????????????????????? 新建事務(wù),如果當(dāng)前存在事務(wù),把當(dāng)前事務(wù)掛起。 ???????????????????????? |
| ???????????????????????? PROPAGATION_NOT_SUPPORTED ???????????????????????? | ???????????????????????? 以非事務(wù)方式執(zhí)行操作,如果當(dāng)前存在事務(wù),就把當(dāng)前事務(wù)掛起。 ???????????????????????? |
| ???????????????????????? PROPAGATION_NEVER ???????????????????????? | ???????????????????????? 以非事務(wù)方式執(zhí)行,如果當(dāng)前存在事務(wù),則拋出異常。 ???????????????????????? |
| ???????????????????????? PROPAGATION_NESTED ???????????????????????? | ???????????????????????? 如果當(dāng)前存在事務(wù),則在嵌套事務(wù)內(nèi)執(zhí)行。如果當(dāng)前沒有事務(wù),則執(zhí)行與PROPAGATION_REQUIRED類似的操作。 ? ? ? ? ? ? ? ? ? ? ? ?? |
此外,還有超時(shí)時(shí)間、是否只讀等相關(guān)功能。
?
?
7、TransactionStatus:保存事務(wù)狀態(tài)
接口提供了一些方法來判斷(獲得)事務(wù)當(dāng)前的狀態(tài):
void flush();沖洗數(shù)據(jù)庫底層會(huì)話
boolean hasSavePoint();返回該事務(wù)是否有一個(gè)保存點(diǎn)
boolean isCompleted();返回事務(wù)是否提交或者回滾
boolean isNewTransaction();返回是否是一個(gè)新事務(wù)
boolean isRollbackOnly();判斷這個(gè)事務(wù)是否已經(jīng)設(shè)置了rollback-only。
void setRollbackOnly();設(shè)置這個(gè)事務(wù)rollback-only。
?
8、嵌套事務(wù)
嵌套是子事務(wù)套在父事務(wù)中執(zhí)行,子事務(wù)是父事務(wù)的一部分。
在進(jìn)入子事務(wù)之前,父事務(wù)建立一個(gè)回滾點(diǎn),叫save point,然后執(zhí)行子事務(wù)。這個(gè)子事務(wù)的執(zhí)行也算是父事務(wù)的一部分,然后子事務(wù)執(zhí)行結(jié)束,父事務(wù)繼續(xù)執(zhí)行。重點(diǎn)就在于那個(gè)save point,看幾個(gè)問題就明白了。
如果子事務(wù)回滾,會(huì)發(fā)生什么?
父事務(wù)會(huì)回滾到進(jìn)入子事務(wù)前建立的save point,然后嘗試其他的事務(wù)或者其他的業(yè)務(wù)邏輯,父事務(wù)之前的操作不會(huì)受到影響,更不會(huì)自動(dòng)回滾。
如果父事務(wù)回滾,會(huì)發(fā)生什么?
父事務(wù)回滾,子事務(wù)也會(huì)跟著回滾!為什么呢,因?yàn)楦甘聞?wù)結(jié)束之前,子事務(wù)是不會(huì)提交的,我們說子事務(wù)是父事務(wù)的一部分,正是這個(gè)道理。
那么:事務(wù)的提交,是什么情況? 是父事務(wù)先提交,然后子事務(wù)提交,還是子事務(wù)先提交,父事務(wù)再提交?
答案是第二種情況,還是那句話,子事務(wù)是父事務(wù)的一部分,由父事務(wù)統(tǒng)一提交。
?
9、Spring支持兩種方式事務(wù)管理
——編程式的事務(wù)管理
-
- 實(shí)際開發(fā)中很少應(yīng)用
- 通過TransactionTemplate手動(dòng)管理事
——使用XML配置聲明事務(wù)
-
- 開發(fā)中推薦使用(代碼侵入性最小)
- Spring的聲明式事務(wù)是通過AOP實(shí)現(xiàn)
?
10、聲明式事務(wù)管理——XML配置(AOP思想)
step-01 配置事務(wù)管理器——注入dataSource,確定對(duì)哪個(gè)數(shù)據(jù)庫操作;
step-02 配置事務(wù)的增強(qiáng)——要做的事務(wù)操作,確定進(jìn)行事務(wù)操作的方法匹配規(guī)則。(隔離級(jí)別、哪個(gè)方法進(jìn)行事務(wù))
step-03 配置切面——把通知應(yīng)用到切點(diǎn)。
?
11、聲明式事務(wù)管理——注解配置
step-01 配置事務(wù)管理器——注入dataSource,確定對(duì)哪個(gè)數(shù)據(jù)庫操作;
step-02 開啟事務(wù)注解;
step-03 在要使用事務(wù)的方法所在類上面添加注解@Transactional。
?
參考:http://opiece.me/2016/03/18/spring-transactional-introduce/
?
轉(zhuǎn)載于:https://www.cnblogs.com/bigbigbigo/p/8383272.html
總結(jié)
以上是生活随笔為你收集整理的Spring实战(十三)Spring事务的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: const常量用法
- 下一篇: JavaScript 通过身份证号获取出