一Spring事務(wù)的種類
1.聲明式事務(wù)
2.編程式事務(wù)
二Spring事務(wù)的具體描述
(一)聲明式事務(wù)
1.聲明式事務(wù)概述
SPRING事務(wù)處理模塊是通過AOP的功能來實(shí)現(xiàn)聲明式事務(wù)處理的。因此,在SPRING事務(wù)處理中,可以通過設(shè)計(jì)一個(gè)TransactionProxyFactoryBean來使用AOP功能,通過這個(gè)TransactionProxyFactoryBean以生成代理對(duì)象,在這個(gè)代理對(duì)象中,通過TransactionInterceptor來完成對(duì)代理方法的攔截,正是這些AOP的攔截功能,將事務(wù)處理的功能編織了進(jìn)來。在Spring的事務(wù)處理中,在實(shí)現(xiàn)聲明式事務(wù)處理時(shí),這是AOP和IOC模塊集成的部分。因此,在SPRING的事務(wù)處理中,對(duì)主要的事務(wù)實(shí)現(xiàn)做了一個(gè)抽象和適配。適配的具體事務(wù)處理器包括:對(duì)DATASOURCE數(shù)據(jù)源的事務(wù)處理支持,對(duì)Hibernate數(shù)據(jù)源的事務(wù)處理支持,對(duì)JDO數(shù)據(jù)源的事務(wù)處理支持,對(duì)JPA和JTA等數(shù)據(jù)源的事務(wù)處理支持。這一系列的事務(wù)處理支持,都是通過設(shè)計(jì)PlatformTransactionManager、AbstractPlatformTransactionManager以及一系列的具體事務(wù)處理器來實(shí)現(xiàn)的,而PlatformTransactionManager又實(shí)現(xiàn)了TransactionInterceptor接口,通過這樣一個(gè)接口實(shí)現(xiàn)設(shè)計(jì),就把這一系列的事務(wù)處理實(shí)現(xiàn)與TransactionProxyFactoryBean結(jié)合了起來,從而形成了spring聲明式事務(wù)處理的設(shè)計(jì)體系。
2.設(shè)計(jì)原理與基本過程
聲明式事務(wù)的實(shí)現(xiàn)大致可以分為以下的幾個(gè)部分:
1)讀取和處理IOC容器中配置的事務(wù)處理屬性,并轉(zhuǎn)化為Spring事務(wù)處理需要的內(nèi)部數(shù)據(jù)結(jié)構(gòu)。具體來說,這里涉及到的類是TransactionAttributrSourceAdvisor,從名字可以看出,它是一個(gè)AOP通知器,SPRING使用這個(gè)通知器來完成對(duì)事務(wù)處理屬性的處理。處理的結(jié)果是,在IOC容器中配置的事務(wù)屬性信息,會(huì)被讀入并轉(zhuǎn)化為TransactionAttribute表示的數(shù)據(jù)對(duì)象,這個(gè)數(shù)據(jù)對(duì)象是Spring對(duì)事務(wù)處理屬性值的數(shù)據(jù)抽象,對(duì)這些屬性的處理時(shí)和TransactionProxyFactoryBean攔截下來的事務(wù)方法的處理結(jié)合起來的。
2)Spring事務(wù)處理模塊的實(shí)現(xiàn)統(tǒng)一的事務(wù)處理過程。這個(gè)通用的事務(wù)處理過程包含處理事務(wù)配置屬性,以及與線程綁定完成事務(wù)處理過程,Spring通過TransactionInfo和TransactionStatus這兩個(gè)數(shù)據(jù)對(duì)象,在事務(wù)處理中記錄和傳遞相關(guān)的執(zhí)行場景。
3)底層的事務(wù)處理實(shí)現(xiàn)。
(二)編程式事務(wù)
1.編程式事務(wù)設(shè)計(jì)原理
在編程式事務(wù)處理的過程中,利用DefaultTransactionDefinition對(duì)象來持有事務(wù)處理實(shí)現(xiàn)。同時(shí),在創(chuàng)建事務(wù)的過程中得到一個(gè)TransactionStatus對(duì)象,然后通過直接調(diào)用transactionManager的commit()和rollback()方法來完成事務(wù)。編程式事務(wù)與聲明式事務(wù)處理的實(shí)現(xiàn)是一致的。
三Spring事務(wù)的具體參數(shù)解釋
readOnly
事務(wù)屬性中的readOnly標(biāo)志表示對(duì)應(yīng)的事務(wù)應(yīng)該被最優(yōu)化為只讀事務(wù)。如果值為true就會(huì)告訴Spring我這個(gè)方法里面沒有insert或者update,你只需要提供只讀的數(shù)據(jù)庫Connection就行了,這種執(zhí)行效率會(huì)比read-write的Connection高,所以這是一個(gè)最優(yōu)化提示。在一些情況下,一些事務(wù)策略能夠起到顯著的最優(yōu)化效果,例如在使用Object/Relational映射工具(如:Hibernate或TopLink)時(shí)避免dirty checking(試圖“刷新”)。
timeout
在屬性中還有定義“timeout”值的選項(xiàng),指定事務(wù)超時(shí)為幾秒。一般不會(huì)使用這個(gè)屬性。在JTA中,這將被簡單地傳遞到J2EE服務(wù)器的事務(wù)協(xié)調(diào)程序,并據(jù)此得到相應(yīng)的解釋。
1.Isolation Level(事務(wù)隔離等級(jí))的5個(gè)枚舉值
為什么事務(wù)要有Isolation Level這個(gè)屬性?先回顧下數(shù)據(jù)庫事務(wù)的知識(shí):
第一類丟失更新(lost update):在完全未隔離事務(wù)的情況下,兩個(gè)事物更新同一條數(shù)據(jù)資源,某一事物異常終止,回滾造成第一個(gè)完成的更新也同時(shí)丟失。
第二類丟失更新(second lost updates):是不可重復(fù)讀的特殊情況,如果兩個(gè)事務(wù)都讀取同一行,然后兩個(gè)都進(jìn)行寫操作,并提交,第一個(gè)事務(wù)所做的改變就會(huì)丟失。
臟讀(dirty read):如果第二個(gè)事務(wù)查詢到第一個(gè)事務(wù)還未提交的更新數(shù)據(jù),形成臟讀。因?yàn)榈谝粋€(gè)事務(wù)你還不知道是否提交,所以數(shù)據(jù)不一定是正確的。
虛讀(phantom read):一個(gè)事務(wù)執(zhí)行兩次查詢,第二次結(jié)果集包含第一次中沒有或者某些行已被刪除,造成兩次結(jié)果不一致,只是另一個(gè)事務(wù)在這兩次查詢中間插入或者刪除了數(shù)據(jù)造成的。
不可重復(fù)讀(unrepeated read):一個(gè)事務(wù)兩次讀取同一行數(shù)據(jù),結(jié)果得到不同狀態(tài)結(jié)果,如中間正好另一個(gè)事務(wù)更新了該數(shù)據(jù),兩次結(jié)果相異,不可信任。
當(dāng)遇到以上這些情況時(shí)我們可以設(shè)置isolation下面這些枚舉值(事務(wù)的隔離級(jí)別):
DEFAULT:采用數(shù)據(jù)庫默認(rèn)隔離級(jí)別
SERIALIZABLE:最嚴(yán)格的級(jí)別,事務(wù)串行執(zhí)行,資源消耗最大;
REPEATABLE_READ:保證了一個(gè)事務(wù)不會(huì)修改已經(jīng)由另一個(gè)事務(wù)讀取但未提交(回滾)的數(shù)據(jù)。避免了“臟讀取”和“不可重復(fù)讀取”的情況,但是帶來了更多的性能損失。
READ_COMMITTED:大多數(shù)主流數(shù)據(jù)庫的默認(rèn)事務(wù)等級(jí),保證了一個(gè)事務(wù)不會(huì)讀到另一個(gè)并行事務(wù)已修改但未提交的數(shù)據(jù),避免了“臟讀取”。該級(jí)別適用于大多數(shù)系統(tǒng)。
READ_UNCOMMITTED:保證了讀取過程中不會(huì)讀取到非法數(shù)據(jù)。隔離級(jí)別在于處理多事務(wù)的并發(fā)問題。
2.關(guān)于propagation屬性的7個(gè)傳播行為
REQUIRED:指定當(dāng)前方法必需在事務(wù)環(huán)境中運(yùn)行,如果當(dāng)前有事務(wù)環(huán)境就加入當(dāng)前正在執(zhí)行的事務(wù)環(huán)境,如果當(dāng)前沒有事務(wù),就新建一個(gè)事務(wù)。這是默認(rèn)值。
SUPPORTS:指定當(dāng)前方法加入當(dāng)前事務(wù)環(huán)境,如果當(dāng)前沒有事務(wù),就以非事務(wù)方式執(zhí)行。
MANDATORY:指定當(dāng)前方法必須加入當(dāng)前事務(wù)環(huán)境,如果當(dāng)前沒有事務(wù),就拋出異常。
REQUIRES_NEW:指定當(dāng)前方法總是會(huì)為自己發(fā)起一個(gè)新的事務(wù),如果發(fā)現(xiàn)當(dāng)前方法已運(yùn)行在一個(gè)事務(wù)中,則原有事務(wù)被掛起,我自己創(chuàng)建一個(gè)屬于自己的事務(wù),直我自己這個(gè)方法commit結(jié)束,原先的事務(wù)才會(huì)恢復(fù)執(zhí)行。
NOT_SUPPORTED:指定當(dāng)前方法以非事務(wù)方式執(zhí)行操作,如果當(dāng)前存在事務(wù),就把當(dāng)前事務(wù)掛起,等我以非事務(wù)的狀態(tài)運(yùn)行完,再繼續(xù)原來的事務(wù)。
NEVER:指定當(dāng)前方法絕對(duì)不能在事務(wù)范圍內(nèi)執(zhí)行,如果方法在某個(gè)事務(wù)范圍內(nèi)執(zhí)行,容器就拋異常,只有沒關(guān)聯(lián)到事務(wù),才正常執(zhí)行。
NESTED:指定當(dāng)前方法執(zhí)行時(shí),如果已經(jīng)有一個(gè)事務(wù)存在,則運(yùn)行在這個(gè)嵌套的事務(wù)中.如果當(dāng)前環(huán)境沒有運(yùn)行的事務(wù),就新建一個(gè)事務(wù),并與父事務(wù)相互獨(dú)立,這個(gè)事務(wù)擁有多個(gè)可以回滾的保證點(diǎn)。就是指我自己內(nèi)部事務(wù)回滾不會(huì)對(duì)外部事務(wù)造成影響,只是針對(duì)DataSourceTransactionManager事務(wù)管理器起效。