Spring.NET教程(十七)事務傳播行為(基礎篇)
上篇我們學習了Spring.net的事務機制。回顧一下,實現事務需要在方法上標記[Transaction]。在很多情況下,事務往往與業務分離。Spring.NET提供了事務代理幫我們管理這些事務,我們可以通過TransactionProxyFactoryObject使用宣告式事務。在很多情況下TransactionProxyFactoryObject比ProxyFactoryObject易用,因為該類可以通過自身屬性來指定事務通知和事務特性,所以不需要單獨為事務通知定義物件。另外,與使用ProxyFactoryObject不同,TransactionProxyFactoryObject不要求使用方法的全名,只用普通的“短”方法名即可。同時,該類可以對方法名進行wild card matching,從而強制我們為DAO的方法使用統一命名規則。
TransactionProxyFactoryObject的TransactionAttributes屬性是用來配置的傳播行為,並規定了7種類型的事務傳播行為,它們規定了事務方法和事務方法發生巢狀呼叫時事務如何進行傳播:
PROPAGATION_REQUIRED 支援當前事務,如果當前沒有事務,就新建一個事務。這是最常見的選擇。
PROPAGATION_SUPPORTS 支援當前事務,如果當前沒有事務,就以非事務方式執行。
PROPAGATION_MANDATORY 支援當前事務,如果當前沒有事務,就丟擲異常。
PROPAGATION_REQUIRES_NEW 新建事務,如果當前存在事務,把當前事務掛起。
PROPAGATION_NOT_SUPPORTED 以非事務方式執行操作,如果當前存在事務,就把當前事務掛起。
PROPAGATION_NEVER 以非事務方式執行,如果當前存在事務,則丟擲異常。
PROPAGATION_NESTED 如果當前存在事務,則在巢狀事務內執行。如果當前沒有事務,則進行與PROPAGATION_REQUIRED類似的操作。
PROPAGATION_REQUIRED和PROPAGATION_SUPPORTS我用的比較多,其它的很少使用。特別是PROPAGATION_REQUIRED,我絕大多數情況都使用這個行為(如,在建立,刪除,修改的時候),我會在查詢(獲取)資料的時候設定為:PROPAGATION_REQUIRED,readOnly,宣告為一個只讀事務,這樣有助於效能的提高。
TransactionProxyFactoryObject的Target屬性是我們要攔截的物件,一般我們設定為業務層的物件。
實現程式碼:
App.config
<?XML version="1.0" encoding="utf-8" ?>
<objects XMLns="http://www.springFramework.net"
xmlns:db="http://www.springframework.net/database">
<db:provider id="DbProvider"
provider="SqlServer-1.1"
connectionString="Server=(local);Database=SpringLesson16;Uid=sa;Pwd=;Trusted_Connection=False"/>
<object id="userDao" type="Dao.UserDao, Dao">
<property name="AdoTemplate" ref="adoTemplate"/>
</object>
<object id="accountDao" type="Dao.AccountDao, Dao">
<property name="AdoTemplate" ref="adoTemplate"/>
</object>
<object id="userService" parent="txProxyTemplate">
<property name="Target">
<object type="Service.UserService, Service">
<property name="UserDao" ref="userDao"/>
<property name="AccountDao" ref="accountDao"/>
</object>
</property>
</object>
<object id="adoTemplate" type="Spring.Data.Core.AdoTemplate, Spring.Data">
<property name="DbProvider" ref="DbProvider"/>
<property name="DataReaderWrapperType" value="Spring.Data.Support.NullMappingDataReader, Spring.Data"/>
</object>
<!--事務管理器-->
<object id="transactionManager"
type="Spring.Data.Core.AdoPlatformTransactionManager, Spring.Data">
<property name="DbProvider" ref="DbProvider"/>
</object>
<object id="txProxyTemplate" abstract="true"
type="Spring.Transaction.Interceptor.TransactionProxyFactoryObject, Spring.Data">
<property name="PlatformTransactionManager" ref="transactionManager"/>
<property name="TransactionAttributes">
<name-values>
<add key="Save*" value="PROPAGATION_REQUIRED"/>
<add key="Delete*" value="PROPAGATION_REQUIRED"/>
<add key="Get*" value="PROPAGATION_REQUIRED,readOnly"/>
</name-values>
</property>
</object>
</objects>
在name-value節點下,key屬性為Save*,意思是攔截所有以Save開頭的方法,在攔截到的方法上增加PROPAGATION_REQUIRED的事務傳播行為。