? ? ? ? 今天我們?nèi)タ匆幌聅pring是怎么管理事務(wù)的。我們先去了解一下事務(wù)的特性和spring事務(wù)的屬性。spring并不是直接去管理事務(wù),而是為JDBC、Hibernate等平臺提供了一個模板接口來實現(xiàn)他們各自的事務(wù)管理器,我們?nèi)タ匆幌拢?/p>

? ? ? ? 先去看看事務(wù)的特性,這些東西都老生常談了(ACID),這里再提一下吧:
? ? ? ? 原子性(Atomicity):原子性是指事務(wù)包含的所有操作要么全部成功,要么全部失敗回滾,這和前面兩篇博客介紹事務(wù)的功能是一樣的概念,因此事務(wù)的操作如果成功就必須要完全應(yīng)用到數(shù)據(jù)庫,如果操作失敗則不能對數(shù)據(jù)庫有任何影響。
? ? ? ? 一致性(Consistency):一致性是指事務(wù)必須使數(shù)據(jù)庫從一個一致性狀態(tài)變換到另一個一致性狀態(tài),也就是說一個事務(wù)執(zhí)行之前和執(zhí)行之后都必須處于一致性狀態(tài)。
? ? ? ? 隔離性(Isolation):隔離性是當(dāng)多個用戶并發(fā)訪問數(shù)據(jù)庫時,比如操作同一張表時,數(shù)據(jù)庫為每一個用戶開啟的事務(wù),不能被其他事務(wù)的操作所干擾,多個并發(fā)事務(wù)之間要相互隔離。
? ? ? ? 持久性(Durability):持久性是指一個事務(wù)一旦被提交了,那么對數(shù)據(jù)庫中的數(shù)據(jù)的改變就是永久性的,即便是在數(shù)據(jù)庫系統(tǒng)遇到故障的情況下也不會丟失提交事務(wù)的操作。
? ? ? ? 我們再來看看spring事務(wù)都有什么屬性:
? ? ? ? 下邊我們分別看一下屬性具體是指什么,首先是事務(wù)的傳播特性

? ? ? ? 傳播特性
? ? ? ? 傳播特性主要有七種,看一下:
? ? ? ? 1、PROPAGATION_REQUIRED:當(dāng)前方法必須運行在事務(wù)中,如果事務(wù)存在,則運行在這個事務(wù)中,事務(wù)不存在就重新開啟一個事務(wù)。(支持事務(wù))
? ? ? ? 2、PROPAGATION_SUPPORTS:表示事務(wù)不是必須的,如果存在事務(wù),則在事務(wù)中運行;如果不存在事務(wù),就以非事務(wù)的方式運行。(支持事務(wù))
? ? ? ? 3、PROPAGATION_MANDATORY:表示方法必須在事務(wù)中運行,否則拋異常。(支持事務(wù))
? ? ? ? 4、PROPAGATION_REQUIRES_NEW:表示了事務(wù)的獨立性。就是每個方法都擁有自己的事務(wù),如果有事務(wù)存在,則將原事務(wù)掛起,重新開啟一個新的事務(wù)。
? ? ? ? 5、PROPAGATION_NOT_SUPPORTED:表示方法不在事務(wù)中運行,如果有事務(wù)存在,則掛起事務(wù)執(zhí)行方法。(不支持事務(wù))
? ? ? ? 6、PROPAGATION_NEVER:不能存在事務(wù)。如果有事務(wù)存在,就拋異常。(不支持事務(wù))
? ? ? ? 7、PROPAGATION_NESTED:表示嵌套事務(wù)。如果當(dāng)前存在事務(wù),則在嵌套事務(wù)內(nèi)執(zhí)行。如果當(dāng)前沒有事務(wù),則執(zhí)行與PROPAGATION_REQUIRED類似的操作。嵌套是子事務(wù)套在父事務(wù)中執(zhí)行,子事務(wù)是父事務(wù)的一部分,在進入子事務(wù)之前,父事務(wù)建立一個回滾點,叫save point,然后執(zhí)行子事務(wù),這個子事務(wù)的執(zhí)行也算是父事務(wù)的一部分,然后子事務(wù)執(zhí)行結(jié)束,父事務(wù)繼續(xù)執(zhí)行。那么問題來了,如果子事務(wù)回滾,父事務(wù)會回滾到之前建立的回滾點(save point);父事務(wù)回滾,子事務(wù)也會跟著回滾。(講道理這個地方真的像極了生活中的父子關(guān)系,兒子犯錯了,父親也有責(zé)任;父親犯錯了,兒子也會收到影響)
? ? ? ? 隔離級別
? ? ? ? 隔離級別主要有三種,分別是:臟讀、幻讀、不可重復(fù)讀。先看看這三種隔離級別都是表示什么
? ? ? ? 臟讀:一個事務(wù)讀到另一個事務(wù)未提交的更新數(shù)據(jù),所謂臟讀,就是指事務(wù)A讀到了事務(wù)B還沒有提交的數(shù)據(jù)。
? ? ? ? 幻讀:幻讀主要是發(fā)生在新增和刪除的情景中。比如第一個事務(wù)執(zhí)行修改操作,這個時候第二個事務(wù)進行新增或刪除操作,導(dǎo)致第一個事務(wù)的結(jié)果有數(shù)據(jù)未修改或者缺少數(shù)據(jù),這種現(xiàn)象被稱作是幻讀。
? ??????不可重復(fù)讀:事務(wù)讀取了兩次數(shù)據(jù),在這兩次的讀取過程中另一個事務(wù)修改了數(shù)據(jù),導(dǎo)致第一個事務(wù)的這兩次讀取出來的數(shù)據(jù)不一樣。這種現(xiàn)象被稱作是不可重復(fù)讀。
? ? ? ? 我們再看一下spring事務(wù)的隔離級別,它這里支持五種,我們分別看一下:
? ? ? ? 1、ISOLATION_DEFAULT:這里就是選擇數(shù)據(jù)庫本身的隔離級別。Mysql的默認(rèn)隔離級別是可重復(fù)讀(ISOLATION_REPEATABLE_READ),Oracle的默認(rèn)隔離級別是讀已提交(ISOLATION_READ_COMMITTED)。
? ? ? ? 2、ISOLATION_READ_UNCOMMITTED:讀未提交。就是臟讀。
? ? ? ? 3、ISOLATION_READ_COMMITTED:讀已提交。可以避免臟讀。
? ? ? ? 4、ISOLATION_REPEATABLE_READ:可重復(fù)讀。避免了可重復(fù)讀,但是還會有幻讀的風(fēng)險。
? ? ? ? 5、ISOLATION_SERIALIZABLE:可串行化。最高級別的隔離級別,成功避免了臟讀、幻讀和不可重復(fù)讀。就好像是串聯(lián)電路一樣,只能夠逐一挨個執(zhí)行,不管多少事務(wù),挨個運行完一個事務(wù)的所有子事務(wù)之后才可以執(zhí)行另外一個事務(wù)里面的所有子事務(wù)。
? ? ? ? 超時
? ? ? ? 所謂事務(wù)超時,就是指一個事務(wù)所允許執(zhí)行的最長時間,如果超過該時間限制但事務(wù)還沒有完成,則自動回滾事務(wù)。在 TransactionDefinition 中以 int 的值來表示超時時間,其單位是秒。 默認(rèn)設(shè)置為底層事務(wù)系統(tǒng)的超時值,如果底層數(shù)據(jù)庫事務(wù)系統(tǒng)沒有設(shè)置超時值,那么就是none,沒有超時限制。
????????只讀
? ??????事務(wù)的只讀屬性是指,對事務(wù)性資源進行只讀操作或者是讀寫操作。所謂事務(wù)性資源就是指那些被事務(wù)管理的資源,比如數(shù)據(jù)源、 JMS 資源,以及自定義的事務(wù)性資源等等。如果確定只對事務(wù)性資源進行只讀操作,那么我們可以將事務(wù)標(biāo)志為只讀的,以提高事務(wù)處理的性能。在 TransactionDefinition 中以 boolean 類型來表示該事務(wù)是否只讀。
? ? ? ? 提到了spring事務(wù),就難免涉及到Transactional這個注解,先看看注解都有什么重要的屬性:

????????看一下是怎么用的,然后講講都是什么意思:

????????說一下這些屬性:
????????value:這個屬性是指定事務(wù)管理器的,沒人把它會放注解上,這個基本上不用。
????????propagation:這里指的是spring事務(wù)的傳播特性,對應(yīng)上邊的七種,默認(rèn)是REQUIRED。
????????isolation:隔離級別,對應(yīng)上邊的五種隔離級別,默認(rèn)值是DEFAULT。
????????timeout:用于設(shè)置事務(wù)的超時秒數(shù),默認(rèn)值為-1表示永不超時。
????????readOnly:該屬性用于設(shè)置當(dāng)前事務(wù)是否為只讀事務(wù),設(shè)置為true表示只讀,false則表示可讀寫,默認(rèn)值為false。從這這個事務(wù)結(jié)束的過程中,其他事務(wù)所提交的數(shù)據(jù),該事務(wù)將看不見?。ú樵冎胁粫霈F(xiàn)別人在我們事務(wù)提交之后提交的數(shù)據(jù))。
????????rollbackFor:該屬性用于設(shè)置需要進行回滾的異常類數(shù)組,當(dāng)方法中拋出指定異常數(shù)組中的異常時,則進行事務(wù)回滾。
????????rollbackForClassName:該屬性用于設(shè)置需要進行回滾的異常類名稱數(shù)組,當(dāng)方法中拋出指定異常名稱數(shù)組中的異常時,則進行事務(wù)回滾。
????????noRollbackFor:該屬性用于設(shè)置不需要進行回滾的異常類數(shù)組,當(dāng)方法中拋出指定異常數(shù)組中的異常時,不進行事務(wù)回滾。
? ??????noRollbackForClassName:該屬性用于設(shè)置不需要進行回滾的異常類名稱數(shù)組,當(dāng)方法中拋出指定異常名稱數(shù)組中的異常時,不進行事務(wù)回滾。
? ? ? ? 在使用的時候要注意:
? ? ? ? 1、要配置<tx:annotation-driven transaction-manager="transactionManager" />來開啟事務(wù)的注解,不配置是沒有效果的。
? ? ? ? 2、只有uncheck exception才會使事務(wù)回滾,checked exception不會使用回滾。如果要在checked exception中讓事務(wù)回滾,在屬性rollbackFor中增加unchecked exception。
? ? ? ? 3、readOnly能不用就不用。
? ? ? ? 4、注解只有在public聲明的類上才會生效。
? ? ? ? 沒有了沒有了!
? ? ? ??
? ??????