1. 程式人生 > >IBATIS事務處理

IBATIS事務處理

        iBATIS事務處理是和Dao緊密相聯的。

        在使用Dao時,如以下程式碼,先插入新記錄,再進行更新:

        UserDao.insertUser (user); // Starts transaction 

        user.setName("wh"); 

        UserDao.updateUser (user); // Starts a new transaction

       因為沒有顯式地啟動事務,iBatis會認為這是兩次事務,分別從連線池中取兩次Connection。我們所寫的Dao子類(繼承自com.ibatis.dao.client.template.SqlMapDaoTemplate)的每一個Dao方法已經預設為一個事務(通過動態代理)。

這樣的事務是隱式事務.

        iBatis是通過DaoManager類來統管Dao子類的事務,

        眾Dao子類由DaoManager產生,如下:

        Reader reader =Resources.getResourceAsReader("dao.xml"); 

        DaoManager  daoManager =DaoManagerBuilder.buildDaoManager(reader); 

        UserDao userDao = (UserDao) daoManager.getDao(UserDao.class);

        UserDao是使用者自己定義的介面,獲得的其實是在dao.xml中指定的相對應的 SqlMapDao實現類,從而實現了鬆藕合。在良好的分層設計中,

        但是一般的事務需要放到業務層,因為一個業務需要具有原子性,事務放到Dao層是不能達到業務一致的效果的,那麼如果想要把事務放到業務層,就需要在業務層使用顯示事務進行宣告處理.

        顯式地宣告事務處理語句,如下:

        try { 

                daoManager.startTransaction(); 

                UserDao.insertUser (user);  

                user.setName("wh"); 

                UserDao.updateUser(user);  

                otherDao.doSomething(other); 

                 ... 

                daoManager.commitTransaction(); 

       } finally { 

                daoManager.endTransaction(); 

       }

       這樣就保持了原子性,整體為一個事務,要麼全部執行成功,否則回滾。

       現在唯一的問題就是,dao層的事務是否已經放棄,否則產生事務巢狀問題對效能會有影響.

       當然,iBatis 完全可以這麼做:建一個宣告式介面:IService,再使用動態代理,將使用者自己的Serivce子類通過動態代理自動包上事務處理的程式碼,預設每一個業務方法為一個事務。

       大師的心如果能輕易揣測,就是不大師了:),估計大師認為這樣屬於過度設計,他認為把這種靈活性交給使用者是合適的,相當多的service 方法只調用一個Dao方法,例如CRUD操作。

       再補充一下,iBatis中對事務的處理是可配置的,最常用的Type是"JDBC",也可以宣告為"JTA"或"EXTERNAL".

       專案裡常用Spring與Ibatis配合使用,這樣可以在Spring裡配置事務管理,可以省去業務層的顯示事務程式碼.

        spring的配置檔案的基本寫法為:

<?xml version="1.0" encoding="UTF-8"?>
<beansxmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
   xmlns:aop="http://www.springframework.org/schema/aop"xmlns:tx="http://www.springframework.org/schema/tx" 
   xmlns:context="http://www.springframework.org/schema/context" 
   xsi:schemaLocation="  
          http://www.springframework.org/schema/beans   
          http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
          http://www.springframework.org/schema/aop   
          http://www.springframework.org/schema/aop/spring-aop-2.0.xsd  
          http://www.springframework.org/schema/tx   
          http://www.springframework.org/schema/tx/spring-tx-2.0.xsd">
         
         
<bean id="dataSource"class="org.apache.commons.dbcp.BasicDataSource" >
   <property name="driverClassName"value="com.mysql.jdbc.Driver" />
   <property name="url"value="jdbc:mysql://10.11.0.145:3306/carrefour?characterEncoding=gb2312"/>
   <property name="username" value="dev01" />
   <property name="password" value="123456"/>
</bean>
<bean id="sqlClient"class="org.springframework.orm.ibatis.SqlMapClientFactoryBean">
   <property name="dataSource">
      <ref local="dataSource" />
   </property>
   <property name="configLocation">
      <value>classpath:sqlmaps.xml</value>
   </property>
</bean>
<!--配置事務管理器-->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <propertyname="dataSource" ref="dataSource"></property>
</bean>
<!--配置哪些方法,什麼情況下需要回滾-->
<tx:advice id="serviceAdvice"transaction-manager="transactionManager"> 
    <tx:attributes>  
        <!--當代理的service層中的方法丟擲異常的時候才回滾,必須加rollback-for引數-->
        <tx:methodname="insert*" propagation="REQUIRED"rollback-for="Throwable"/>
        <tx:methodname="del*" propagation="REQUIRED"rollback-for="Throwable"/> 
        <tx:methodname="update*" propagation="REQUIRED"rollback-for="Throwable"/> 
        <!--除了上面標識的方法,其他方法全是隻讀方法-->
        <tx:methodname="*" read-only="true"/> 
    </tx:attributes> 
</tx:advice> 
<!-- 配置哪些類的方法需要進行事務管理 --> 
<aop:config proxy-target-class="true"> 
<aop:pointcut id="servicePointcut"expression="execution(* com.wh.service.*.*(..))"/> 
<aop:advisor pointcut-ref="servicePointcut"advice-ref="serviceAdvice"/> 
</aop:config>

         這是在spring+Ibatis的情況下, ,通過aop控制需要事務的包和具體方法,將事務控制在service層,來達到事務在業務層提交和回滾.保持業務的原子性.