首先介紹下spring的事務(wù)傳播規(guī)則和隔離級別
PROPAGATION_REQUIRED
如果存在一個(gè)事務(wù),則支持當(dāng)前事務(wù)。如果沒有事務(wù)則開啟一個(gè)新的事務(wù)。
PROPAGATION_SUPPORTS
如果存在一個(gè)事務(wù),支持當(dāng)前事務(wù)。如果沒有事務(wù),則非事務(wù)的執(zhí)行。但是對于事務(wù)同步的事務(wù)管理器,PROPAGATION_SUPPORTS與不使用事務(wù)有少許不同。
PROPAGATION_MANDATORY
如果已經(jīng)存在一個(gè)事務(wù),支持當(dāng)前事務(wù)。如果沒有一個(gè)活動的事務(wù),則拋出異常。
?
PROPAGATION_REQUIRES_NEW
總是開啟一個(gè)新的事務(wù)。如果一個(gè)事務(wù)已經(jīng)存在,則將這個(gè)存在的事務(wù)掛起。
PROPAGATION_NOT_SUPPORTED
總是非事務(wù)地執(zhí)行,并掛起任何存在的事務(wù)。
PROPAGATION_NEVER
總是非事務(wù)地執(zhí)行,如果存在一個(gè)活動事務(wù),則拋出異常
PROPAGATION_NESTED
如果一個(gè)活動的事務(wù)存在,則運(yùn)行在一個(gè)嵌套的事務(wù)中. 如果沒有活動事務(wù), 則按TransactionDefinition.PROPAGATION_REQUIRED 屬性執(zhí)
PROPAGATION_NESTED 與PROPAGATION_REQUIRES_NEW的區(qū)別
:它們非常類似,都像一個(gè)嵌套事務(wù),如果不存在一個(gè)活動的事務(wù),都會開啟一個(gè)新的事務(wù)。使用PROPAGATION_REQUIRES_NEW時(shí),內(nèi)層事務(wù)與外層事務(wù)就像兩個(gè)獨(dú)立的事務(wù)一樣,一旦內(nèi)層事務(wù)進(jìn)行了提交后,外層事務(wù)不能對其進(jìn)行回滾。兩個(gè)事務(wù)互不影響。兩個(gè)事務(wù)不是一個(gè)真正的嵌套事務(wù)。同時(shí)它需要JTA事務(wù)管理器的支持。
使用PROPAGATION_NESTED時(shí),外層事務(wù)的回滾可以引起內(nèi)層事務(wù)的回滾。而內(nèi)層事務(wù)的異常并不會導(dǎo)致外層事務(wù)的回滾,它是一個(gè)真正的嵌套事務(wù)。DataSourceTransactionManager使用savepoint支持PROPAGATION_NESTED時(shí),需要JDBC 3.0以上驅(qū)動及1.4以上的JDK版本支持。其它的JTA TrasactionManager實(shí)現(xiàn)可能有不同的支持方式。
PROPAGATION_REQUIRED應(yīng)該是我們首先的事務(wù)傳播行為。它能夠滿足我們大多數(shù)的事務(wù)需求。
?
在TransactionDefinition接口中定義了五個(gè)不同的事務(wù)隔離級別
ISOLATION_DEFAULT
這是一個(gè)PlatfromTransactionManager默認(rèn)的隔離級別,使用數(shù)據(jù)庫默認(rèn)的事務(wù)隔離級別.另外四個(gè)與JDBC的隔離級別相對應(yīng)
ISOLATION_READ_UNCOMMITTED
這是事務(wù)最低的隔離級別,它充許別外一個(gè)事務(wù)可以看到這個(gè)事務(wù)未提交的數(shù)據(jù)。這種隔離級別會產(chǎn)生臟讀,不可重復(fù)讀和幻像讀。
ISOLATION_READ_COMMITTED
保證一個(gè)事務(wù)修改的數(shù)據(jù)提交后才能被另外一個(gè)事務(wù)讀取。另外一個(gè)事務(wù)不能讀取該事務(wù)未提交的數(shù)據(jù)。這種事務(wù)隔離級別可以避免臟讀出現(xiàn),但是可能會出現(xiàn)不可重復(fù)讀和幻像讀。
ISOLATION_REPEATABLE_READ
這種事務(wù)隔離級別可以防止臟讀,不可重復(fù)讀。但是可能出現(xiàn)幻像讀。它除了保證一個(gè)事務(wù)不能讀取另一個(gè)事務(wù)未提交的數(shù)據(jù)外,還保證了避免下面的情況產(chǎn)生(不可重復(fù)讀)。
ISOLATION_SERIALIZABLE
這是花費(fèi)最高代價(jià)但是最可靠的事務(wù)隔離級別。事務(wù)被處理為順序執(zhí)行。除了防止臟讀,不可重復(fù)讀外,還避免了幻像讀。
我們使用TransactionProxyFactoryBean完成spring的事務(wù)管理,他有一個(gè)屬性是transactionAttributeSource,這個(gè)屬性被定義成為一個(gè)TransactionAttributeSource實(shí)例
我們現(xiàn)在的目的是讓courseService類的enrollStudentInCourse被spring進(jìn)行事務(wù)控制,配置文件如下:
?
<
bean?
id
="dataSource"
?class
="org.springframework.jdbc.datasource.DriverManagerDataSource"
>
??????
<
property?
name
="driverClassName"
>
?????????
<
value
>
com.sybase.jdbc3.jdbc.SybDriver
</
value
>
???????
</
property
>
???????
<
property?
name
="url"
>
?????????
<
value
>
jdbc:sybase:Tds:192.168.0.10:4100/DB_CENTER?charset=eucgb
&
jconnect_version=4
?????????
</
value
>
???????
</
property
>
???????
<
property?
name
="username"
>
?????????
<
value
>
sa
</
value
>
???????
</
property
>
???????
<
property?
name
="password"
>
?????????
<
value
></
value
>
???????
</
property
>
???
</
bean
>
????
<
bean?
id
="TransactionManager"
?class
="org.springframework.jdbc.datasource.DataSourceTransactionManager"
>
?????????
<
property?
name
="dataSource"
>
?????????????
<
ref?
bean
="dataSource"
/>
?????????
</
property
>
????
</
bean
>
?
????
<
bean?
id
="sessionFactory"
????????class
="org.springframework.orm.hibernate3.LocalSessionFactoryBean"
>
????????
<
property?
name
="dataSource"
>
????????????
<
ref?
local
="dataSource"
?
/>
????????
</
property
>
????????
<
property?
name
="hibernateProperties"
>
????????????
<
props
>
????????????????
<
prop?
key
="hibernate.dialect"
>
????????????????????org.hibernate.dialect.SybaseDialect
????????????????
</
prop
>
????????????????
<
prop?
key
="hibernate.show_sql"
>
false
</
prop
>
????????????????
<
prop?
key
="hibernate.cache.use_query_cache"
>
true
</
prop
>
????????????????
<
prop?
key
="hibernate.cache.provider_class"
>
????????????????????org.hibernate.cache.HashtableCacheProvider
????????????????
</
prop
>
????????????
</
props
>
????????
</
property
>
????????
<
property?
name
="mappingResources"
>
???????????
<
list
>
?????????????
<
value
>
com/bjjdsy/ky/zl/domain/ZlStationTab.hbm.xml
</
value
>
???????????
</
list
>
????????
</
property
>
????
</
bean
>
????
<!--
?以下是事務(wù)配置?
-->
????
????
<
bean?
id
="transactionAttributeSource"
?class
="org.springframework.transaction.interceptor.NameMatchTransactionAttributeSource"
>
???????
<
property?
name
="properties"
>
??????????
<
props
>
????????????
<
prop?
key
="enrollStudentInCourse"
>
???????????????PROPAGATION_REQUIRES_NEW,ISOLATION_REPEATABLE_READ,readonly,-CourseException?
<!--
?表示當(dāng)拋出CourseException時(shí)進(jìn)行回滾,用減號表示,加號表示拋出異常仍可進(jìn)行提交?
-->
????????
????????????
</
prop
>
??????????
</
props
>
???????
</
property
>
????
</
bean
>
????
????
<
bean?
id
="courseService"
?class
="org.springframework.transaction.interceptor.TransactionProxyFactoryBean"
>
??????
<
property?
name
="proxyInterfaces"
>
????????
<
value
>
com.test.CourseService
</
value
>
??????
</
property
>
??????
<
property?
name
="target"
>
????????
<
value
>
courseServiceImpl
</
value
>
??????
</
property
>
??????
<
property?
name
="transactionManager"
>
????????
<
ref?
bean
="TransactionManager"
/>
??????
</
property
>
??????
<
property?
name
="trainsactionAttributeSource"
>
????????
<
ref?
bean
="transactionAttributeSource"
/>
??????
</
property
>
????
</
bean
>
?
我們也可以使用通配符進(jìn)行操作,改動如下:
?
?
<
bean?
id
="transactionAttributeSource"
?class
="org.springframework.transaction.interceptor.NameMatchTransactionAttributeSource"
>
???????
<
property?
name
="properties"
>
??????????
<
props
>
????????????
<
prop?
key
="enroll*"
>
???????????????PROPAGATION_REQUIRES_NEW,ISOLATION_REPEATABLE_READ,readonly,-CourseException?
<!--
?表示當(dāng)拋出CourseException時(shí)進(jìn)行回滾,用減號表示,加號表示拋出異常仍可進(jìn)行提交?
-->
????????
????????????
</
prop
>
??????????
</
props
>
???????
</
property
>
????
</
bean
>
?
除此之外,我們還有一種名稱匹配事務(wù)的捷徑,這種方式不再使用trainsactionAttributeSource而使用transactionAttributes
類似如下定義Bean
?
??
<
bean?
id
="stationManager"
?class
="org.springframework.transaction.interceptor.TransactionProxyFactoryBean"
>
???????
<
property?
name
="transactionManager"
>
??????????
<
ref?
bean
="transactionManager"
></
ref
>
???????
</
property
>
??????
<
property?
name
="target"
>
??????????
<
bean?
class
="com.bjjdsy.ky.zl.service.StationServiceImpl"
>
????????????
<
property?
name
="stationDAO"
>
????????????????
<
ref?
bean
="StationDAO"
/>
???????????
</
property
>
??????????
</
bean
>
??????
</
property
>
??????
<
property?
name
="transactionAttributes"
>
????????
<
props
>
??????????
<
prop?
key
="save*"
>
PROPAGATION_REQUIRED
</
prop
>
??????????
<
prop?
key
="list*"
>
PROPAGATION_REQUIRED,readOnly
</
prop
>
??????????
<
prop?
key
="delete*"
>
PROPAGATION_REQUIRED
</
prop
>
??????????
<
prop?
key
="get*"
>
PROPAGATION_REQUIRED,readOnly
</
prop
>
??????????
<
prop?
key
="edit*"
>
PROPAGATION_REQUIRED
</
prop
>
??????????
<
prop?
key
="search*"
>
PROPAGATION_REQUIRED
</
prop
>
???????
</
props
>
?????
</
property
>
????
</
bean
>
Spring聲明式事務(wù)之NameMatchAtttirbuteSource使用