1. 程式人生 > >Spring如何設定讓事務自動提交和回滾?Spring兩種事務管理方式的配置及使用

Spring如何設定讓事務自動提交和回滾?Spring兩種事務管理方式的配置及使用

1,我們要明確,Spring如何設定讓事務自動提交和回滾?

       ①如何自動提交?

          理論上,可以通過對DataSource如下設定,讓事務自動提交

  1. <!-- 配置資料來源 -->
  2. <beanid="dataSource"class="org.apache.commons.dbcp.BasicDataSource">
  3.    <propertyname="defaultAutoCommit"value="true"></property>
  4. </bean>

          實際上,這個設定對於大多數資料來源是沒有必要的,例如"org.apache.commons.dbcp.BasicDataSource"

        (我們可以通過反編譯外掛或者反編譯工具瀏覽該jar包),我們發現

  1. public BasicDataSource() {  
  2.     this.defaultAutoCommit = true;  
  3.     this.defaultReadOnly = null;  
  4. /*此類通過無參的構造方法例項化:new BasicDataSource()*/

         上述表明:該資料來源通過構造方法,初始化成員變數,defaultAutoCommit預設為true。

     ②如何自動回滾?

2,想要Spring對事務實現自動管理,首先我們要為資料來源配置事務管理器

        SSH中配置如下:

    1. <!-- 配置資料來源 -->
    2. <beanid="dataSource"class="org.apache.commons.dbcp.BasicDataSource">
    3.     <propertyname="driverClassName"value="${jdbc_driverClassName}"></property>
    4. </bean>

  1. <!-- 配置SessionFactory -->
  2. <beanid="sessionFactory"class="org.springframework.orm.hibernate4.LocalSessionFactoryBean"
    >
  3.     <propertyname="dataSource"ref="dataSource"/>
  4. </bean>
  5. <!-- 配置一個事務管理器 -->
  6. <beanid="transactionManager"
  7.     class="org.springframework.orm.hibernate4.HibernateTransactionManager">
  8.     <propertyname="sessionFactory"ref="sessionFactory"/>
  9. </bean>
SSM中配置如下:
  1. <!-- 配置資料來源 -->
  2. <beanid="dataSource"class="org.apache.commons.dbcp.BasicDataSource">
  3.     <propertyname="driverClassName"value="${jdbc_driverClassName}"></property>
  4. </bean>
  5. <!-- 配置事務管理器 --> 
  6. <beanname="transactionManager"
  7.     class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
  8.     <propertyname="dataSource"ref="dataSource"/>
  9. </bean>

         總結:Mybatils與hibernate在事務管理配置上有差別 —— Mybatils通常使用Spring預設的資料來源事務管理器只要求相同資料來源,不做其他配置;Hibernate使用專門的Spring事務管理器需要引用具備相同資料來源的SessionFactory。

3,Spring的事務管理方式有哪幾種?如何配置並使用?(事務管理器建立完成,以它為基礎配置事務標識——用來建立並管理事務)

           包含兩種: 程式設計式事務管理宣告式事務管理

              (一)其中程式設計式管理帶來程式碼冗餘,違背Spring簡潔特性,基本上很少使用,例如:

  1.     int a=consumpDao.insert(s);//插入消費明細
  2.     int b=customerDao.insert(customer);//此處實際應該update(customer),不然會出現重複主鍵的異常
  3.     int d=0;  
  4.     if(a*b*d==1){  
  5.         json.put("result",0);  
  6.         json.put("msg""購買成功");  
  7.         json.put("data""");  
  8.     }else{  
  9.         json.put("result",-1);  
  10.         json.put("msg""購買失敗");  
  11.         json.put("data""");  
  12.         TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();  
  13.     }  

                其中使用程式TransactionAspectSupport.currentTransactionStatus().setRollbackOnly(); 在沒有異常丟擲的情況下實現

       注意:儘管可以採用程式設計式方法回滾事務,但“回滾”只是事務的生命週期之一,所以要麼程式設計實現事務的全部必要週期,要麼仍要

           配置務切點,即,將事務管理的其他週期交由Spring的標識!

          (二)其中宣告式管理符合Spring的特性,被廣泛使用 —— 註解易於配置,配置易於程式設計 ,它的實現具有兩種常用方式:

                ①一種是基於tx和aop切面攔截的xml配置檔案:

  1. <tx:adviceid="transactionAdvice"transaction-manager="transactionManager">
  2. <!-- 切點攔截的位置下,所有形式類似的方法名,‘事務’都會交由相應事務管理工具管理-->
  3.     <tx:attributes>
  4.         <tx:methodname="insert*"propagation="REQUIRED"/>
  5.         <tx:methodname="get*"propagation="REQUIRED"read-only="true"/>
  6.     </tx:attributes>
  7. </tx:advice>
  8. <aop:configexpose-proxy="true">
  9.     <aop:pointcutid="transactionPointcut"expression="execution(* com.local.*.*.*(..))"/>
  10.     <aop:advisorpointcut-ref="transactionPointcut"advice-ref="transactionAdvice"/>
  11. </aop:config>
                需要注意一下expression中*萬用字元的含義:
  1. <!-- 對所有層的事務方法進行切點攔截 *的含義:①所有返回型別 ②所有包③所有類 ④所有方法(..)標識方法內的所有引數  -->
                當然,大多數時候我們都是在service層,實現事務管理的,即配置如下:
  1. <aop:configexpose-proxy="true">
  2.     <aop:pointcutid="transactionPointcut"expression="execution(* com.local.service.*.*(..))"/>
  3.     <aop:advisorpointcut-ref="transactionPointcut"advice-ref="transactionAdvice"/>
  4. </aop:config>
                只要在expression描述的範圍下,方法名符合配置格式,事務的 ①開啟  ②提交  ③回滾   ④關閉  ⑤清空就會依據具體配置交由Spring管理:
  1. @RequestMapping("consump")  
  2. publicvoid insertConsumption(Customer c,Consumption s,Mygift m) throws Exception{        
  3.     JSONObject json =new JSONObject();  

  ②另一種就是基於@Transactional註解:

  1. <!-- 註解方式配置事物 -->
  2.     <tx:annotation-driventransaction-manager="transactionManager"/>
              @Transactional 可以作用於介面、介面方法、類以及類方法上。當作用於類上時,該類的所有 public 方法將都具有該型別的事務屬性,同時,我們也可以在方法級別使用該標註來覆蓋類級別的定義。
  1. @Transactional
  2. @RequestMapping("consump")  
  3. publicvoid insertConsumption(Customer c,Consumption s,Mygift m) throws Exception{        
  4.     JSONObject json =new JSONObject();