事物管理:這個有點抽象,書面表達是這樣的:
爲了完成對數據的操作,企業應用經常要求併發訪問在多個構件之間共享的數據。這些應用在下列條件下應該維護數據的完整性(由應用的商務規則來定義): 分佈式訪問一個單獨的數據資源,以及從一個單獨的應用構件訪問分佈式資源。 在這種情況,可能要求在(分佈式)資源上的一組操作被當作一個工作單元(unit)。在一個工作單元中, 操作的所有部分一起成功或失敗並恢復。在下面的情況下這個問題更加複雜: 通過一組分佈式的、訪問多個資源的數據的構件實現一個工作單元,和/或部分操作是被順序執行的或在要求協調和/或同步的並行線程中。 在所有情況下, 都要求應用維護一個工作單元的成功或失敗。在失敗的情況下,所有資源要把數據狀態返回到以前的狀態 (比如說,工作單元開始前的狀態)。 事務的概念和和事務管理器(或者一個事務處理服務)在一個工作單元中的維護數據完整性,這就簡化了這樣的企業級別分佈式應用的構造。 一個事務是有下列屬性的一個工作單元: 原子性(ATOMICITY): 一個事務要被完全的無二義性的做完或撤消。在任何操作出現一個錯誤的情況下,構成事務的所有操作的效果必須被撤消,數據應被回滾到以前的狀態。 一致性(CONSISTENCY): 一個事務應該保護所有定義在數據上的不變的屬性(例如完整性約束)。在完成了一個成功的事務時,數據應處於一致的狀態。換句話說,一個事務應該把系統從一個一致-狀態轉換到另一個一致狀態。舉個例子,在關係數據庫的情況下, 一個一致的事務將保護定義在數據上的所有完整性約束。 隔離性(ISOLATION): 在同一個環境中可能有多個事務併發執行,而每個事務都應表現爲獨立執行。串行的執行一系列事務的效果應該同於併發的執行它們。這要求兩件事: 在一個事務執行過程中,數據的中間的(可能不一致)狀態不應該被暴露給所有的其他事務。 兩個併發的事務應該不能操作同一項數據。數據庫管理系統通常使用鎖來實現這個特徵。 持久性(DURABILITY): 一個被完成的事務的效果應該是持久的。 說的狹隘一點:就是你做你的事,我做我的事,但對事務的基本特徵卻沒什麼改變。比如說是一工具箱,我借鉗子,你也借鉗子,但我時間上比你早那麼一點點,我用完了再給你,給你的還是一鉗子,而不是鈑手,而且你用的時候,東西也沒壞。 公共的東西就是要保護好,大家都要用的。 這裏我就說說要常用的spring的事務管理。 spring 有聲明式,也有編碼式的。編碼的開發我是很少用 就說說聲明的吧 。 這個要用到一個概念叫AOP(Aspect Oriented Programming).說白了就是在你的程序外面包層東西,讓他符合這個事務的特性。
Spring也提供聲明式事務管理。這是通過AOP實現的。大多數Spring用戶選擇聲明式事務管理,這是最少影響應用代碼的選擇,因而這是和非侵入性的輕量級容器的觀念是一致的。
1)通常通過TransactionProxyFactoryBean設置Spring事務代理。需要一個目標對象包裝在事務代理中。這個目標對象一般是一個普通Javabean。當我們定義TransactionProxyFactoryBean時,必須提供一個相關的PlatformTransactionManager的引用和事務屬性。事務屬性含有事務定義。例如:
<bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory"/>
</bean>
這玩藝就是相關的 PlatformTransactionManager的引用和事務屬性。
然後主體到了:
- <bean id="transactionService"class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
- <property name="transactionManager">
- <ref local="transactionManager"/>
- </property>
- <property name="target">
- <ref local="transactionServiceControl"/>
- </property>
- <property name="transactionAttributes">
- <props>
- <prop key=”insert*”>PROPAGATION_REQUIRED,-MyCheckedException</prop>
- <prop key=”update*”>PROPAGATION_REQUIRED</prop>
- <prop key=”*”>PROPAGATION_REQUIRED,readOnly</prop>
- </props>
- </property>
- </bean>
事務代理會實現目標對象的接口:這裏是屬性名是target的引用。id是transactionServiceControl。(使用CGLIB也可以實現具體類的代理。只要設置proxyTargetClass屬性爲true即可。如果目標對象沒有實現任何接口,這將自動設置該屬性爲true。通常,我們希望面向接口編程。)使用proxyInterfaces屬性來限定事務代理來代理指定接口也是可以。也可以通過從org.springframework.aop.framework.ProxyConfig繼承或所有AOP代理工廠共享的屬性來定製TransactionProxyFactoryBean行爲。
然後,說說屬性名是transactionAttributes意義:
這裏的transactionAttributes屬性是定義在org.springframework.transaction.interceptor.NameMathTransactionAttributeSource中的屬性格式設置。這個包括通配符的方法名稱映射是很直觀的,如”insert*”。注意insert*的映射的值包括回滾規則。”-MyCheckException”指定如果方法拋出MyCheckException或它的子類,事務會自動回滾。可以用逗號分隔多個回滾規則。“-”前綴強制回滾,“+”前綴指定提交(這允許即使拋出unchecked異常時也可以提交事務)。“PROPAGATION_REQUIRED”指定事務傳播範圍。
TransactionProxyFactoryBean允許你通過“preInterceptors”和“postInterceptors”屬性設置前或後的攔截操作。可以設置任意數量的前和後通過,它們的類型可以是Advistor(切入點),MethodInterceptor或被當前Spring配置支持的通知類型。例如:ThrowAdvice,AfterReturningAdvice或BeforeAdvice。這些通知必須支持實例共享模式。如果你需要高級AOP特性操作事務,通過org.springframework.aop.framework.ProxyFactoryBean,而不是TransactionProxyFactory實用代理創建者。
-----------------------------------------------------------------------------------------
這個是簡單的,對每一個邏輯,也就是代碼中的action來進行處理。這樣做的話,可能最後變成配置地獄,此時可以考慮使用自動事務代理。 根據spring的BeanName來管理自動代理可以這樣做: <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd"> <beans> <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"> <property name="driverClassName"> <value>com.mysql.jdbc.Driver</value> </property> <property name="url"> <value>jdbc:mysql://localhost:3306/myuser</value> </property> <property name="username"> <value>lighter</value> </property> <property name="password"> <value>12345</value> </property> </bean> <bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean"> <property name="dataSource" ref="dataSource" /> <property name="hibernateProperties"> <props> <prop key="hibernate.dialect"> org.hibernate.dialect.MySQLDialect </prop> <prop key="hibernate.show_sql">true</prop> </props> </property> <property name="mappingResources"> <list> <value>org/mmc/dao/domain/User.hbm.xml</value> </list> </property> </bean> <!-- 配置Hibernate的事務管理器 --> <bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager"> <property name="sessionFactory" ref="sessionFactory" /> </bean> <!-- 定義事務攔截器bean --> <bean id="transactionInterceptor" class="org.springframework.transaction.interceptor.TransactionInterceptor"> <property name="transactionManager" ref="transactionManager" /> <property name="transactionAttributes"> <props> <prop key="insert*">PROPAGATION_REQUIRED</prop> <prop key="find*">PROPAGATION_REQUIRED,readOnly</prop> <prop key="*">PROPAGATION_REQUIRED</prop> </props> </property> </bean> <!-- 定義BeanNameAutoProxyCreator--> <bean class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator"> <property name="beanNames"> <!-- 所有名字以DAO,Service結尾的bean,將由該"bean後處理器"爲其創建事務代理;實際上應該在業務層進行事務管理,這裏只是舉一個簡單例子 --> <value>*DAO,*Service</value> </property> <!-- 下面定義BeanNameAutoProxyCreator所需的事務攔截器--> <property name="interceptorNames"> <list> <!-- 可以增加其他的攔截器 --> <value>transactionInterceptor</value> </list> </property> </bean> <!-- 舉下面這一個例子:這時候,這一個bean已經有了事務管理,可以增加類似的bean --> <bean id="searchUserDAO" class="org.mmc.dao.impl.SearchUserDAO"> <property name="sessionFactory" ref="sessionFactory" /> </bean> </beans> ----------------------------------------------------- 下面再看一種也是常用的使用bean繼承簡化事務代理配置 <bean id="test1" class="test.TransactionTestImpl"> <property name="ds"><ref local="dataSource"/></property> </bean> <bean id="test2" class="test.TestImpl"> <property name="ds"><ref local="dataSource"/></property> </bean> <bean id="baseTxProxy" lazy-init="true" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean" abstract="true"> <property name="transactionManager"><ref bean="transactionManager"/></property> <property name="transactionAttributes"> <props> <prop key="*">PROPAGATION_REQUIRED</prop> </props> </property> </bean> <bean id="testTrans1" parent="baseTxProxy"> <property name="target"> <ref local="test1"/> </property> </bean> <bean id="testTrans2" parent="baseTxProxy"> <property name="target"> <ref local="test2"/> </property> </bean> 使用繼承的方法,其配置文件是增量式的,不如採用上面所說的第一種方法簡捷,精煉。 ok 就這麼多,不知道說明白沒有。呵呵
http://www.douban.com/note/433877038/