宣告式事务处理

Spring提供宣告式事務管理(declarative transaction management),這是藉由Spring AOP所提供的功能,不過現階段您不必太理會Spring AOP的部份,藉由基本的配置,您就可以使用宣告式的事務管理,Spring的事務管理依賴於aopalliance.jar與cglib*.jar,您可以在lib目錄的aopalliance與cglib目錄下找到這兩個檔案。

  使用宣告式事務管理的好處是,事務管理不侵入您所開發的組件,具體來說,您的DAO物件不會意識到正在事務管理之中,而且如果您想要改變事務管理策略的話,也只需要在定義檔中重新組態即可。

  例如,我們設計的DAO物件:

 代碼:

UserDAO.java
package onlyfun.caterpillar; 

import javax.sql.DataSource; 
import org.springframework.jdbc.core.*; 

public class UserDAO { 
    private DataSource dataSource; 
    private JdbcTemplate jdbcTemplate; 

    public void setDataSource(DataSource dataSource) { 
        this.dataSource = dataSource; 
        jdbcTemplate = new JdbcTemplate(dataSource); 
    } 
        
    public void insertUser(User user) { 
        jdbcTemplate.update("INSERT INTO USER VALUES....."); 
        .... 
    } 
    
    .... 
}

  如上面所示的,我們的DAO物件中並沒有任何與事務管理相關的代碼。要進行宣告式事務管理,一個簡化的方法是使用TransactionProxyFactoryBean,指定要介入的事務管理對象及其方法,例如我們的Bean定義檔如下:

 代碼:

<?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.springframework.jdbc.datasource.DriverManagerDataSource"> 
        <property name="driverClassName"> 
            <value>com.mysql.jdbc.Driver</value> 
        </property> 
        <property name="url"> 
            <value>jdbc:mysql://localhost:3306/TestDB</value> 
        </property> 
        <property name="username"> 
            <value>caterpillar</value> 
        </property> 
        <property name="password"> 
            <value>123456</value> 
        </property> 
    </bean> 

    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> 
        <property name="dataSource"> 
            <ref bean="dataSource"/> 
        </property>    
    </bean> 
    
    <bean id="userDAO" class="onlyfun.caterpillar.UserDAO"> 
        <property name="dataSource"> 
            <ref bean="dataSource"/> 
        </property> 
    </bean> 
    
    <bean id="userDAOProxy" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean"> 
        <property name="transactionManager"> 
            <ref bean="transactionManager"/> 
        </property> 
        <property name="target"> 
            <ref bean="userDAO"/> 
        </property> 
        <property name="transactionAttributes"> 
            <props> 
                <prop key="insert*">PROPAGATION_REQUIRED</prop> 
            </props> 
        </property>        
    </bean> 
</beans>

  TransactionProxyFactoryBean需要一個transactionManager,由於我們直接使用JDBC,所以這邊使用DataSourceTransactionManager,TransactionProxyFactoryBean是個代理物件,target屬性指定要代理的對象,事務管理會自動介入指定的方法前後,這邊使用transactionAttributes屬性指定,insert*表示指定方法名稱insert開頭的都要納入事務管理,您也可以指定方法全名,如果在方法執行過程中發生錯誤,則所有操作自動撤回,否則正常提交。

  insert*等方法上指定了PROPAGATION_REQUIRED,表示在目前的事務中執行操作,如果事務不存在就建立一個新的,相關的常數意義都可以在API文件中TransactionDefinition介面中找到。您可以加上多個事務定義,中間使用逗號 "," 區隔,例如您可以加上唯讀,或者是指定某個例外發生時撤回操作:

 代碼:

PROPAGATION_REQUIRED,readOnly,-MyCheckedException

  MyCheckedException前面加上"-"時,表示發生指定例外時撤消操作,如果前面加上"+",表示發生例外時立即 提交。

  由於userDAO被userDAOProxy代理了,所以我們要作的是取得userDAOProxy,而不是userDAO,例如:

 代碼:

ApplicationContext context = new FileSystemXmlApplicationContext("bean.xml"); 
UserDAO userDAO = (UserDAO) context.getBean("userDAOProxy"); 
userDAO.insertUser(user);

  上面介紹的是簡化過後的宣告式事務管理,您可以不處理一些細節問題即得到Spring事務管理的好處,事實上,您可以設定不同的TransactionInterceptor來得到更多的細節處理,這只需要修改配置檔,其它不用作任何修改,然而這涉及到AOP的概念較多,這邊先不作太多的介紹,而僅先就達成相同功能為目的,將上例的配置檔作個修改作為一個示範,如果您有興趣可以先看看詳細的配置是如何設定的:

 代碼:

<?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.springframework.jdbc.datasource.DriverManagerDataSource"> 
        <property name="driverClassName"> 
            <value>com.mysql.jdbc.Driver</value> 
        </property> 
        <property name="url"> 
            <value>jdbc:mysql://localhost:3306/TestDB</value> 
        </property> 
        <property name="username"> 
            <value>root</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="transactionInterceptor" class="org.springframework.transaction.interceptor.TransactionInterceptor"> 
        <property name="transactionManager"> 
            <ref bean="transactionManager"/> 
        </property> 
        <property name="transactionAttributeSource"> 
            <value> 
                onlyfun.caterpillar.UserDAO.insert*=PROPAGATION_REQUIRED 
            </value> 
        </property> 
    </bean> 
                                                                                
    <bean id="userDAO" class="onlyfun.caterpillar.UserDAO"> 
        <property name="dataSource"> 
            <ref bean="dataSource"/> 
        </property> 
    </bean> 
    
    <bean id="userDAOProxy" class="org.springframework.aop.framework.ProxyFactoryBean"> 
        <property name="interceptorNames"> 
            <value>transactionInterceptor,userDAO</value> 
        </property> 
    </bean> 
</beans>
 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值