1. TransactionDefinition接口中定義五個(gè)隔離級(jí)別:
ISOLATION_DEFAULT 這是一個(gè)PlatfromTransactionManager默認(rèn)的隔離級(jí)別,使用數(shù)據(jù)庫默認(rèn)的事務(wù)隔離級(jí)別.另外四個(gè)與JDBC的隔離級(jí)別相對(duì)應(yīng);
ISOLATION_READ_UNCOMMITTED 這是事務(wù)最低的隔離級(jí)別莹菱,它充許別外一個(gè)事務(wù)可以看到這個(gè)事務(wù)未提交的數(shù)據(jù)。這種隔離級(jí)別會(huì)產(chǎn)生臟讀召庞,不可重復(fù)讀和幻像讀俩檬。
ISOLATION_READ_COMMITTED 保證一個(gè)事務(wù)修改的數(shù)據(jù)提交后才能被另外一個(gè)事務(wù)讀取柒莉。另外一個(gè)事務(wù)不能讀取該事務(wù)未提交的數(shù)據(jù)。這種事務(wù)隔離級(jí)別可以避免臟讀出現(xiàn)尘吗,但是可能會(huì)出現(xiàn)不可重復(fù)讀和幻像讀逝她。
ISOLATION_REPEATABLE_READ 這種事務(wù)隔離級(jí)別可以防止臟讀,不可重復(fù)讀睬捶。但是可能出現(xiàn)幻像讀汽绢。它除了保證一個(gè)事務(wù)不能讀取另一個(gè)事務(wù)未提交的數(shù)據(jù)外,還保證了避免下面的情況產(chǎn)生(不可重復(fù)讀)侧戴。
ISOLATION_SERIALIZABLE 這是花費(fèi)最高代價(jià)但是最可靠的事務(wù)隔離級(jí)別。事務(wù)被處理為順序執(zhí)行跌宛。除了防止臟讀酗宋,不可重復(fù)讀外,還避免了幻像讀疆拘。
Dirty reads(臟讀)。也就是說哎迄,比如事務(wù)A的未提交(還依然緩存)的數(shù)據(jù)被事務(wù)B讀走回右,如果事務(wù)A失敗回滾,會(huì)導(dǎo)致事務(wù)B所讀取的的數(shù)據(jù)是錯(cuò)誤的漱挚。
non-repeatable reads(數(shù)據(jù)不可重復(fù)讀)翔烁。比如事務(wù)A中兩處讀取數(shù)據(jù)-total-的值。在第一讀的時(shí)候旨涝,total是100蹬屹,然后事務(wù)B就把total的數(shù)據(jù)改成 200,事務(wù)A再讀一次白华,結(jié)果就發(fā)現(xiàn)慨默,total竟然就變成200了,造成事務(wù)A數(shù)據(jù)混亂弧腥。
phantom reads(幻象讀數(shù)據(jù))厦取,這個(gè)和non-repeatable reads相似,也是同一個(gè)事務(wù)中多次讀不一致的問題管搪。但是non-repeatable reads的不一致是因?yàn)樗〉臄?shù)據(jù)集被改變了(比如total的數(shù)據(jù))虾攻,但是phantom reads所要讀的數(shù)據(jù)的不一致卻不是他所要讀的數(shù)據(jù)集改變,而是他的條件數(shù)據(jù)集改變更鲁。比如Select account.id where account.name=”ppgogo*”,第一次讀去了6個(gè)符合條件的id台谢,第二次讀取的時(shí)候,由于事務(wù)b把一個(gè)帳號(hào)的名字由”dd”改成”ppgogo1”岁经,結(jié)果取出來了7個(gè)數(shù)據(jù)朋沮。
3. 在TransactionDefinition接口中定義了七個(gè)事務(wù)傳播行為:
1)?PROPAGATION_REQUIRED 如果存在一個(gè)事務(wù),則支持當(dāng)前事務(wù)。如果沒有事務(wù)則開啟一個(gè)新的事務(wù)樊拓。這是我們使用最多的事務(wù)傳播行為?
例如方法A中調(diào)用方法B,如果在調(diào)用A時(shí)沒有事務(wù)則開啟一個(gè)事務(wù)纠亚,而對(duì)于B則會(huì)加入到A的事務(wù)中。?
使用spring聲明式事務(wù)筋夏,spring使用AOP來支持聲明式事務(wù)蒂胞,會(huì)根據(jù)事務(wù)屬性,自動(dòng)在方法調(diào)用之前決定是否開啟一個(gè)事務(wù)条篷,并在方法執(zhí)行之后決定事務(wù)提交或回滾事務(wù).
2)PROPAGATION_SUPPORTS 如果存在一個(gè)事務(wù)骗随,支持當(dāng)前事務(wù)。如果沒有事務(wù)赴叹,則非事務(wù)的執(zhí)行鸿染。但是對(duì)于事務(wù)同步的事務(wù)管理器,PROPAGATION_SUPPORTS與不使用事務(wù)有少許不同乞巧。
3)PROPAGATION_MANDATORY 如果已經(jīng)存在一個(gè)事務(wù)涨椒,支持當(dāng)前事務(wù)。如果沒有一個(gè)活動(dòng)的事務(wù)绽媒,則拋出異常throw new IllegalTransactionStateException(“Transaction propagation ‘mandatory’ but no existing transaction found”);蚕冬。
4)PROPAGATION_REQUIRES_NEW 總是開啟一個(gè)新的事務(wù)。如果一個(gè)事務(wù)已經(jīng)存在是辕,則將這個(gè)存在的事務(wù)掛起囤热。使用PROPAGATION_REQUIRES_NEW,需要使用 JtaTransactionManager作為事務(wù)管理器。
5)PROPAGATION_NOT_SUPPORTED 總是非事務(wù)地執(zhí)行获三,并掛起任何存在的事務(wù)赢乓。使用PROPAGATION_NOT_SUPPORTED,也需要使用JtaTransactionManager作為事務(wù)管理器。
6)PROPAGATION_NEVER 總是非事務(wù)地執(zhí)行石窑,如果存在一個(gè)活動(dòng)事務(wù)牌芋,則拋出異常;
7)PROPAGATION_NESTED如果一個(gè)活動(dòng)的事務(wù)存在松逊,則運(yùn)行在一個(gè)嵌套的事務(wù)中. 如果沒有活動(dòng)事務(wù), 則按TransactionDefinition.PROPAGATION_REQUIRED 屬性執(zhí)行躺屁。這是一個(gè)嵌套事務(wù),使用JDBC 3.0驅(qū)動(dòng)時(shí),僅僅支持DataSourceTransactionManager作為事務(wù)管理器。需要JDBC 驅(qū)動(dòng)的java.sql.Savepoint類经宏。有一些JTA的事務(wù)管理器實(shí)現(xiàn)可能也提供了同樣的功能犀暑。使用PROPAGATION_NESTED,還需要把PlatformTransactionManager的nestedTransactionAllowed屬性設(shè)為true;而 nestedTransactionAllowed屬性值默認(rèn)為false;
使用JDBC的時(shí)候開啟事務(wù)使用Connection烁兰,而使用Hibernate時(shí)開啟事務(wù)使用的是Session耐亏。所以如果我們使用傳統(tǒng)的事務(wù)編程策略時(shí),程序代碼必須和具體的事務(wù)操作代碼耦合沪斟。這樣在不同的事務(wù)策略之間切換時(shí)開發(fā)者必須手動(dòng)改代碼广辰。而如果使用Spring來管理事務(wù)則不會(huì)出現(xiàn)這種情況。
Spring事務(wù)策略是通過PlatformTransactionManager接口實(shí)現(xiàn)的,它是整個(gè)Spring事務(wù)的核心择吊。它是對(duì)事務(wù)策略的一個(gè)高度抽象李根,不依賴于任何具體的事務(wù)策略,而對(duì)于底層的具體的事務(wù)策略它相應(yīng)的有不同的實(shí)現(xiàn)類几睛。而對(duì)于不同的事務(wù)策略的切換通常由Spring容器來負(fù)責(zé)管理房轿,應(yīng)用程序既無須與具體的事務(wù)API耦合,也無須與特定的實(shí)現(xiàn)類耦合而將應(yīng)用和持久化技術(shù)所森,事務(wù)API徹底分離開來囱持。
Spring事務(wù)管理的策略模式體現(xiàn)在哪?PlatformTransactionManager代表事務(wù)管理接口,但它并不知道底層到底如何管理事務(wù)的焕济,而它只要求事務(wù)管理提供開始事務(wù)(getTransaction(TransactionDefinition definition)),提交事務(wù)(commit())和回滾事務(wù)(rollback())三個(gè)方法纷妆,具體的實(shí)現(xiàn)交給子類來完成。
源碼:
publicinterfacePlatformTransactionManager{//獲得事務(wù)TransactionStatus? getTransaction(TransactionDefinition definition)throwsTransactionException;//事務(wù)提交voidcommit(TransactionStatus status)throwsTransactionException;//事務(wù)回滾voidrollback(TransactionStatus status)throwsTransactionException ;}
在核心接口PlatformTransactionManager中吼蚁,方法getTransaction(TransactionDefinition definition)中它接受一個(gè)TransactionDefinition對(duì)象返回一個(gè)TransactionStatus。TransactionStatus對(duì)象表示一個(gè)事務(wù)问欠,被關(guān)聯(lián)在當(dāng)前執(zhí)行的線程上肝匆。返回的事務(wù)可以是個(gè)新事務(wù),也可以是個(gè)已經(jīng)存在的事務(wù)對(duì)象
TransactionDefinition接口必須指定如下的幾個(gè)屬性值:
事務(wù)隔離
事務(wù)傳播
事務(wù)超時(shí)(即事務(wù)最長持續(xù)時(shí)間)
只讀狀態(tài)(Hibernate很有用的優(yōu)化)
TransactionStatus:代表事務(wù)本身顺献,它提供了通用的事務(wù)管理如控制事務(wù)的執(zhí)行和查詢事務(wù)狀態(tài)的方法旗国。?
源碼:
publicinterfaceTransactionStatus{booleanisNewTransaction();//是否為新建事務(wù)voidsetRollbackOnly();//設(shè)置事務(wù)回滾booleanisRollBackOnly();//查詢事務(wù)是否已有回滾標(biāo)志}
幾個(gè)類之間的關(guān)系:?
7.Spring對(duì)不同的持久化技術(shù)提供的不同實(shí)現(xiàn)類
Spring具體的事務(wù)管理由PlatformTransactionManager的不同實(shí)現(xiàn)類來完成,在Spring容器中配置PlatformTransactionManager Bean時(shí)注整,必須針對(duì)不同的環(huán)境來配置不同的實(shí)現(xiàn)類能曾。
下面分別展示了在JDBC和Hibernate中配置PlatformTransactionManager對(duì)應(yīng)的實(shí)現(xiàn)類。?
JDBC
Hibernate
對(duì)于Spring通過的兩種事務(wù)管理肿轨。編程式的事務(wù)管理程序直接從容器中獲取transactionManager Bean寿冕,該Bean總是PlatformTransactionManager的實(shí)例,所以可以使用它的三個(gè)方法來管理事務(wù)椒袍。而對(duì)于聲明式事務(wù)管理只需要要在XML配置文件中配置事務(wù)代理即可驼唱,在目標(biāo)方法中開發(fā)者無需編寫額外的代碼,不依賴Spring或任何其他事務(wù)的API驹暑。
Spring提供了tx:命名空間來配置事務(wù)管理玫恳,tx:下的配置事務(wù)增強(qiáng)處理,最后使用元素啟用自動(dòng)代理优俘。?
元素除了需要transaction-manager之外京办,還需要子元素,該子元素包含多個(gè)子元素帆焕,用來配置事務(wù)的屬性惭婿。?
的重要屬性:
propagation:事務(wù)傳播行為 默認(rèn)是REQUIRED
isolation:事務(wù)隔離級(jí)別?
timeout:超時(shí)時(shí)間