1.1 Spring事務管理及方式

Spring是SSH中的管理員,負責管理其它框架,協調各個部分的工作。今天一起學習一下Spring的事務管理。Spring的事務管理分爲聲明式跟編程式。聲明式就是在Spring的配置文件中進行相關配置(XML和註解);編程式就是代碼中添加事務,如回滾等。事務攔截器和事務自動代理方式實現原理:像Struts2一樣,都是憑藉強大的攔截器功能對業務邏輯方法的調用進行攔截,然後又BeanNameAutoProxyCreator自動生成事務代理,最後送事務管理器,統一管理。
Spring配置文件中關於事務配置總是由三個組成部分,分別是DataSource、TransactionManager和代理機制這三部分,無論哪種配置方式,一般變化的只是代理機制這部分。 DataSource、TransactionManager這兩部分只是會根據數據訪問方式有所變化,比如使用Hibernate進行數據訪問時,DataSource實際爲SessionFactory,TransactionManager的實現爲HibernateTransactionManager。 有聲明式事務管理和編程式事務管理。
spring是靠AOP的方法攔截異常去判斷是否需要事務回滾或提交的。你自己把異常給catch了,又不往上拋出 別人怎麼知道你的方法是否執行正常呢。(可以拋出運行時異常就可以)
http://java.chinaitlab.com/Spring/841714_4.html
1.spring在進行聲明時事務管理時,通過捕獲Service層方法的DataAccessException來提交和回滾事務的,而Service層方法的DataAccessException又是來自調用DAO層方法所產生的異常.
2.我們一般在寫DAO層代碼時,如果繼承JdbcDaoSupport 類,並使用此類所實現的JdbcTemplate來執行數據庫操作,此類會自動把低層的SQLException轉化成DataAccessException以及DataAccessException的子類.
3.一般在Service層我們可以自己捕獲DAO方法所產成的DataAccessException,然後再拋出一個業務方法有意義的異常(ps:此異常最好繼承DataAccessException),然後在Web層捕獲,這樣我們就可以手動編碼的靈活實現通過業務方法執行的成功和失敗來向用戶轉發不同的頁面.)

下面一起看看兩種(XML和註解)聲明式事務的具體配置:
聲明式事務
XML:
公共配置

  1. <!-- 配置sessionFactory -->  
  2. <bean id="sessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">  
  3.     <property name="configLocation">  
  4.         <value>classpath:config/hibernate.cfg.xml</value>  
  5.     </property>  
  6.     <property name="packagesToScan">  
  7.         <list>  
  8.             <value>com.entity</value>  
  9.         </list>  
  10.     </property>  
  11. </bean>  
  12.   
  13. <!-- 配置事務管理器(聲明式的事務) -->  
  14. <bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">  
  15.     <property name="sessionFactory" ref="sessionFactory"></property>  
  16. </bean>  
  17.   
  18. <!-- 配置DAO -->   
  19. <bean id="userDao" class="com.dao.UserDaoImpl">  
  20.     <property name="sessionFactory" ref="sessionFactory"></property>  
  21. </bean>  


第一種,使用tx標籤方式

  1. <!-- 第一種配置事務的方式 ,tx-->  
  2. <tx:advice id="txadvice" transaction-manager="transactionManager">  
  3.     <tx:attributes>  
  4.         <tx:method name="add*" propagation="REQUIRED" rollback-for="Exception" />  
  5.         <tx:method name="modify*" propagation="REQUIRED" rollback-for="Exception" />  
  6.         <tx:method name="del*" propagation="REQUIRED" rollback-for="Exception"/>  
  7.         <tx:method name="*" propagation="REQUIRED" read-only="true"/>  
  8.     </tx:attributes>  
  9. </tx:advice>  
  10.   
  11. <aop:config>  
  12.     <aop:pointcut id="daoMethod" expression="execution(* com.dao.*.*(..))"/>  
  13.     <aop:advisor pointcut-ref="daoMethod" advice-ref="txadvice"/>  
  14. </aop:config>  
expression="execution(* com.dao.*.*(..))"
其中第一個*代表返回值,第二*代表dao下子包,第三個*代表方法名,“(..)”代表方法參數。
第二種,使用代理方式

  1. <!-- 第二種配置事務的方式 ,代理-->  
  2. <bean id="transactionProxy"  
  3.     class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean" abstract="true">  
  4.     <property name="transactionManager" ref="transactionManager"></property>  
  5.     <property name="transactionAttributes">  
  6.         <props>  
  7.             <prop key="add*">PROPAGATION_REQUIRED, -Exception</prop>  
  8.             <prop key="modify*">PROPAGATION_REQUIRED, -Exception</prop>  
  9.             <prop key="del*">PROPAGATION_REQUIRED, -Exception</prop>  
  10.             <prop key="*">PROPAGATION_REQUIRED, readOnly</prop>  
  11.         </props>  
  12.     </property>  
  13. </bean>  
  14. <bean id="userDao" parent="transactionProxy">  
  15.     <property name="target">  
  16.         <!-- 用bean代替ref的方式-->  
  17.         <bean class="com.dao.UserDaoImpl">  
  18.             <property name="sessionFactory" ref="sessionFactory"></property>  
  19.         </bean>  
  20.     </property>  
  21. </bean>  
將transactionProxy的abstract屬性設置爲"true",然後將具體的Dao的parent屬性設置爲"transactionProxy",可以精簡代碼。

第三種,使用攔截器

  1. <!-- 第三種配置事務的方式,攔截器 (不常用)-->  
  2. <bean id="transactionInterceptor" class="org.springframework.transaction.interceptor.TransactionInterceptor">  
  3.     <property name="transactionManager" ref="transactionManager"></property>  
  4.     <property name="transactionAttributes">  
  5.         <props>  
  6.             <prop key="add*">PROPAGATION_REQUIRED, -Exception</prop>  
  7.             <prop key="modify*">PROPAGATION_REQUIRED, -Exception</prop>  
  8.             <prop key="del*">PROPAGATION_REQUIRED, -Exception</prop>  
  9.             <prop key="*">PROPAGATION_REQUIRED, readOnly</prop>  
  10.         </props>  
  11.     </property>  
  12. </bean>  
  13. <bean id="proxyFactory" class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator">  
  14.     <property name="interceptorNames">  
  15.         <list>  
  16.             <value>transactionInterceptor</value>  
  17.         </list>  
  18.     </property>  
  19.     <property name="beanNames">  
  20.         <list>  
  21.             <value>*Dao</value>  
  22.         </list>  
  23.     </property>  
  24. </bean>  


Spring事務類型詳解:


PROPAGATION_REQUIRED--支持當前事務,如果當前沒有事務,就新建一個事務。這是最常見的選擇。

PROPAGATION_SUPPORTS--支持當前事務,如果當前沒有事務,就以非事務方式執行。

PROPAGATION_MANDATORY--支持當前事務,如果當前沒有事務,就拋出異常。

PROPAGATION_REQUIRES_NEW--新建事務,如果當前存在事務,把當前事務掛起。

PROPAGATION_NOT_SUPPORTED--以非事務方式執行操作,如果當前存在事務,就把當前事務掛起。

PROPAGATION_NEVER--以非事務方式執行,如果當前存在事務,則拋出異常。

PROPAGATION_NESTED--如果當前存在事務,則在嵌套事務內執行。如果當前沒有事務,則進行與PROPAGATION_REQUIRED類似的操作。


註解:

採用註解的方式,需要注意的是,使用註解的方式需要在Spring的配置文件中加入一句話:<context:annotation-config />,其作用是開啓註解的方式。具體配置如下:

  1. <!--開啓註解方式-->  
  2. <context:annotation-config />  
  3.   
  4. <!-- 配置sessionFactory -->  
  5. <bean id="sessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">  
  6.     <property name="configLocation">  
  7.         <value>classpath:config/hibernate.cfg.xml</value>  
  8.     </property>  
  9.     <property name="packagesToScan">  
  10.         <list>  
  11.             <value>com.entity</value>  
  12.         </list>  
  13.     </property>  
  14. </bean>  
  15.   
  16. <!-- 配置事務管理器 -->  
  17. <bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">  
  18.     <property name="sessionFactory" ref="sessionFactory"></property>  
  19. </bean>  
  20.   
  21. <!-- 第四種配置事務的方式,註解 -->  
  22. <tx:annotation-driven transaction-manager="transactionManager"/>  

註解文件:

  1. package com.dao;  
  2.   
  3. import org.springframework.orm.hibernate3.HibernateTemplate;  
  4. import org.springframework.transaction.annotation.Propagation;  
  5. import org.springframework.transaction.annotation.Transactional;  
  6.   
  7. import com.entity.User;  
  8.   
  9. @Transactional  
  10. public class UserDaoImpl_BAK extends HibernateTemplate {  
  11.   
  12.     @Transactional(propagation=Propagation.REQUIRED,rollbackForClassName="Exception")  
  13.     public void addUser(User user) throws Exception {  
  14.         this.save(user);  
  15.     }  
  16.   
  17.     @Transactional(propagation=Propagation.REQUIRED,rollbackForClassName="Exception")  
  18.     public void modifyUser(User user) {  
  19.         this.update(user);  
  20.     }  
  21.   
  22.     @Transactional(propagation=Propagation.REQUIRED,rollbackForClassName="Exception")  
  23.     public void delUser(String username) {  
  24.         this.delete(this.load(User.class, username));  
  25.     }  
  26.   
  27.     @Transactional(readOnly=true)  
  28.     public void selectUser() {  
  29.   
  30.     }  
  31.   
  32. }
類頭的@Transactional爲默認事務配置,如方法沒有自己的事務類型,則按默認事務,如有自己的配置,則按自己的配置。


編程式事務



程序中手動添加事務:

Connection conn = null;  
UserTransaction tx = null;  
try {  
    tx = getUserTransaction();                       //1.獲取事務  
    tx.begin();                                    //2.開啓JTA事務  
    conn = getDataSource().getConnection();           //3.獲取JDBC  
    //4.聲明SQL  
    String sql = "select * from INFORMATION_SCHEMA.SYSTEM_TABLES";  
    PreparedStatement pstmt = conn.prepareStatement(sql);//5.預編譯SQL  
    ResultSet rs = pstmt.executeQuery();               //6.執行SQL  
    process(rs);                                   //7.處理結果集  
    closeResultSet(rs);                             //8.釋放結果集  
    tx.commit();                                  //7.提交事務  
} catch (Exception e) {  
    tx.rollback();                                 //8.回滾事務  
    throw e;  
} finally {  
   conn.close();                                //關閉連接  
}  
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章