《電子技術應用》
您所在的位置:首頁 > 嵌入式技術 > 設計應用 > Spring 3.x的事務處理機制的研究比較
Spring 3.x的事務處理機制的研究比較
來源:微型機與應用2012年第10期
丁振凡
(華東交通大學 信息工程學院, 江西 南昌 330013)
摘要: Spring提供了多樣化的事務編程支持,包括編程式事務和聲明式事務。針對JDBC的事務處理對各類實現(xiàn)方式進行了介紹,并對實現(xiàn)效率進行了比較。當事務處理量少時,可以考慮用基于JDBC模板的編程式事務,當事務涉及量大時建議用基于@Transactional注解的聲明式事務。
Abstract:
Key words :

摘   要: Spring提供了多樣化的事務編程支持,包括編程式事務和聲明式事務。針對JDBC的事務處理對各類實現(xiàn)方式進行了介紹,并對實現(xiàn)效率進行了比較。當事務處理量少時,可以考慮用基于JDBC模板的編程式事務,當事務涉及量大時建議用基于@Transactional注解的聲明式事務。
關鍵詞: Spring 3.x;事務處理;@Transactional注解;JDBC模板

    事務是訪問數(shù)據(jù)庫的一個基本單位,通常用一個操作序列表示。事務ACID特性,即原子性、一致性、獨立性和持久性。一個事務處理包括一系列操作,并把它們當做整體失敗或成功的單個操作對待。傳統(tǒng)JDBC的Connection類中含有幾個方法實現(xiàn)對事務的處理支持,setAutoCommit方法設置事務是否自動提交,commit方法進行事務提交,rollback方法實現(xiàn)事務回滾。傳統(tǒng)的JDBC事務編程將程序代碼與事務操作代碼耦合在一起。而Spring面向的是各種數(shù)據(jù)訪問方式,包括JDBC、Hibernate、JTA、JTS等。因此,需要一個統(tǒng)一的策略。
    Spring 是一個以控制倒轉(IoC)原則和面向方面編程思想(AOP)為基礎的輕量級框架。Spring因其優(yōu)良的性能、強大的功能吸引了眾多應用開發(fā)者的興趣。Spring提供的事務管理可以分為編程式和聲明式兩類[1]。根據(jù)事務涉及范圍,可將事務分為基于JTA的全局事務和針對具體數(shù)據(jù)庫操作的局部事務。而在具體數(shù)據(jù)庫操作方式上,Spring既實現(xiàn)了基于JDBC的事務處理,又實現(xiàn)了基于Hibernate的事務處理。本文以JDBC事務為樣例進行介紹。
1 Spring的編程式事務處理
    Spring提供了幾個關于事務處理的接口,在編程時常用。它們是:
    (1)TransactionDefinition:定義事務屬性的接口;
    (2)TransactionStatus:定義事務管理狀態(tài)的接口;
    (3)PlatformTransactionManager:用于管理事務的基礎接口。
    Spring的事務管理是一種典型的策略模式,PlatformTransactionManager代表事務管理接口,但它不知道底層如何管理事務,只要求管理者提供開始事務(getTransaction)、提交事務(commit)和回滾事務(rollback)三個方法,具體實現(xiàn)交給實現(xiàn)類完成。JDBC事務的具體實現(xiàn)類是DataSourceTransactionManager。
    編程式事務可分為兩種實現(xiàn)方式,一種是由TransactionTemplate進行事務管理,另一種是由JdbcTemplate進行事務管理。程序中用到的事務管理器可通過配置注入。例如:
<!—指定事務管理器 –->
<bean id="myTransactionManager"
   class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
     <property name="dataSource">
         <ref bean="dataSource"/>  <!—dataSource的注入配
        置略 -->
      </property>
  </bean>  
<bean id=”userDAO” class=” ecjtu.userDAO”>  <!—業(yè)務邏輯Bean -->
     <property name=”dataSource”>
        <ref bean=”dataSource”/>
    </property>
    <property name=”transactionManager”>  <!—將事務管理
        器注入業(yè)務邏輯—>
        <ref bean=”myTransactionManager”>  
    </property>
</bean>
1.1 由TransactionTemplate進行事務處理
     Spring的TransactionTemplate在編程中可省去事務提交、回滾代碼。只需將訪問數(shù)據(jù)庫的操作代碼安排在TransactionTemplate的處理框架內,Spring 將自動進行 commit 和 rollback處理。TransactionTemplate是采用回調機制實現(xiàn)方法調用。
     具體實現(xiàn)的核心代碼如下,代碼中的事務管理器通過配置注入。
    TransactionTemplate transactionTemplate=
       new TransactionTemplate(mytransactionManager);
    transactionTemplate.execute(
      new TransactionCallbackWithoutResult() {        
        public void doInTransactionWithoutResult(Transaction
            Status status) {
              …… // 這里安排業(yè)務邏輯處理
         }
      } 
    );
1.2 由JdbcTemplate的執(zhí)行結果決定事務提交和回滾
    為簡化對JDBC數(shù)據(jù)源的訪問處理,Spring提供了JdbcTemplate類。基于JdbcTemplate的事務處理與傳統(tǒng)的JDBC事務非常類似,它根據(jù)程序執(zhí)行SQL是否出現(xiàn)異常決定事務是提交還是回滾。具體實現(xiàn)框架如下:
DefaultTransactionDefinition def=new DefaultTransactionDefinition();
TransactionStatus status= transactionManager.getTransaction(def); try {
    JdbcTemplate jdbcTemplate=new JdbcTemplate(dataSource);    for ( int k=0;k<usernames.length;k++) {                                    //批量插入若干帳戶
      String sql="insert into user values(′"+prefix+k+"′,′"+
               "111111′,’’,′"+usernames[k]+ "′,10) ";
         jdbcTemplate.execute(sql);  
                                   //通過JdbcTemplate執(zhí)行SQL語句
       }
       transactionManager.commit(status);                //事務提交
}
catch( DataAccessException ex)  {          //出現(xiàn)數(shù)據(jù)訪問異常
    transactionManager.rollback(status);                //事務回滾
}
2 Spring聲明式事務處理
    Spring聲明式事務處理使用了IoC和AOP思想,因此,需要將相關的JAR包加入到類路徑中。聲明式事務處理不需要在具體業(yè)務邏輯中加入任何事務處理代碼。它是通過在配置文件中用屬性設置來聲明業(yè)務邏輯中的哪些操作需要進行事務處理[2]。
    后續(xù)配置中數(shù)據(jù)源、事務管理器、userDAO的定義和前面的相同,為節(jié)省篇幅予以省略。以下分別討論聲明式事務的幾種實現(xiàn)方式。
2.1 用事務攔截器進行事務管理
    Spring的事務攔截器(TransactionInterceptor)通過對方法執(zhí)行的攔截加入事務管理。TransactionInterceptor類有兩個主要的屬性: transactionManager屬性實現(xiàn)與事務管理器的關聯(lián);transactionAttributes 屬性用來定義事務規(guī)則。
    <bean id = "transactionInterceptor" class=
   "org.springframework.transaction.interceptor.Transaction-
            Interceptor">
    <property name="transactionManager">
          <ref bean="myTransactionManager"/>
    </property>
    <property name="transactionAttributeSource">
    <value>ecjtu.UserDao. insertUsers *=PROPAGATION_RE-
    QUIRED</value>
    </property>
</bean>
  說明:上面配置指明對于ecjtu.UserDao類的insertUsers方法使用PROPAGATION_REQUIRED的事務傳播規(guī)則進行事務處理。該傳播特性的意思是,如果執(zhí)行方法前已在事務中,則利用該事務,否則創(chuàng)建一個新事務來執(zhí)行方法。
2.2 用TransactionProxyFactoryBean進行事務管理
    TransactionProxyFactoryBean創(chuàng)建了一個JDK代理,該代理會攔截目標對象的方法調用。對于名字出現(xiàn)在transactionAttributes屬性的key中的任何方法,代理會使用指定的傳播方式來開啟一個事務。以下為配置舉例。
<bean id="userDAOProxy"
class="org.springframework.transaction.interceptor.Transaction-
        ProxyFactoryBean">
        <property name="transactionManager">
           <ref bean="myTransactionManager "/>
      </property>
       <property name="target">
             <ref bean="userDAO"/> 
        </property>
        <property name="transactionAttributes">
        <props> 
             <!-- 表示對所有以insert和save開頭的方法
            進行事務處理  -->
        <prop key="insert*">PROPAGATION_REQUIRED</
            prop>
        <prop key="save*">PROPAGATION_REQUIRED</
            prop>
       </props>
</property>
</bean>
     該配置方式的明顯缺點是要為每個有事務處理要求的bean配置一個代理bean ,這樣配置文件的內容增加非???。
2.3 使用@Transactional注解
    Spring還提供了@Transactional全注解的事務配置,它具有功能強大、簡單明了的特點。@Transactional注解可修飾類,也可修飾方法。修飾類表示對整個類起作用;修飾方法則僅對方法起作用[3]。
    例如,以下代碼在insertUsers方法上加上@Transactional注解,則該方法在執(zhí)行過程中將自動進行事務處理。
    public class UserDaoImpl  implements UserDao {
       @Transactional (propagation = Propagation.REQUIRED)
    public void  insertUsers(String prefix, String[ ]usernames) {
             for (int k=0;k<usernames.length;k++)
                 register(prefix+k,"111111","",usenames[k],10);
        }
       }
2.3.1 相關配置
    要讓Spring啟用對annotation的支持,在beans.xml配置文件中要有如下行:
    <context:annotation-config />
    為了讓Spring根據(jù)Annotation來配置事務代理,還需要指定事務管理器。
    <tx:annotation-driven transaction-manager=" myTransactionManager "/>
2.3.2 使用@Transactional的幾點注意
    (1)聲明式事務配置后,相關Bean將建立事務代理。所以從系統(tǒng)環(huán)境獲取Bean和訪問Bean均要通過接口,不要通過具體實現(xiàn)類來獲取Bean。
    (2)@Transactional只能被應用到public方法上,實際接口中的方法均為public,除非不屬于接口的方法。
    (3)默認情況下,一個有事務的方法, 遇到RuntimeException 時會回滾,遇到受檢查的異常是不會回滾的。要想所有異常都回滾,要加上rollbackFor屬性來指定。例如:
    @Transactional(rollbackFor=Exception.class)
3 幾種事務管理的測試對比

 


    以下對幾種事務處理方法進行測試對比,參見表1。實驗選擇批量插入30個學生,分別對正常插入操作完成和出現(xiàn)異常導致回滾所花費時間代價進行測試。測試結果表明,在聲明式事務處理中,使用Spring的事務注解方式執(zhí)行效率高,而在編程式事務處理中,基于JDBC模板執(zhí)行結果進行事務處理執(zhí)行效率也較好,但編程稍復雜。
    Spring提供了多樣化的事務編程支持,包括編程式事務和聲明式事務。任何事務處理方式都需要有事務管理器的支持。Spring的編程式事務適合對局部操作進行事務處理。如果應用系統(tǒng)中有大量的事務需要處理,則應該使用聲明式事務處理。聲明式事務處理實現(xiàn)了事務處理與業(yè)務邏輯的分離,聲明式事務處理依賴Spring AOP的功能。在3種聲明式處理中,用TransactionProxyFactoryBean實現(xiàn)的事務處理,需要為涉及事務處理的每個Bean設置一個代理,配置量大。用事務攔截器方式執(zhí)行效率不夠理想。而基于@Transactional注解的事務定義方法具有配置簡單、編程和執(zhí)行效率高的特點,是值得推薦的方式。
參考文獻
[1] 李濤,張波,張曉鵬,等. Spring 框架的事務管理應用分析[J].計算機與信息技術,2006(7):8-9.
[2] 李剛.輕量級Java EE企業(yè)應用實踐(第3版)-Struts2+Spring3+Hibernate整合開發(fā)[M].北京:北京電子工業(yè)出版社,2011.
[3] 劉榮輝.基于Annotation的Spring事務應用設計[J].微型電腦應用,2009,25(7):57-59.

此內容為AET網(wǎng)站原創(chuàng),未經(jīng)授權禁止轉載。