1. 程式人生 > >Spring.NET教程(十七)事務傳播行為(基礎篇)

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的事務傳播行為。