spring ibatis事务一个误区分析

先看段经典的ibatis spring配置,注意我的配置中没有配置spring的声明式事务:
         <!-- ======================================================================== -->
         <!-- DataSource定义。 -->
         <!-- ======================================================================== -->
         <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"
                   destroy-method="close">
                   <property name="driverClassName" value="**" />
                   <property name="url" value="**" />
                   <property name="username" value="**" />
                   <property name="password" value="**" />
                   <property name="defaultAutoCommit" value="true or false" /> <!---请先不关心这个配置,后面会说道--
         </bean>

         <!-- ======================================================================== -->
         <!-- TransactionManager定义。 -->
         <!-- ======================================================================== -->
         <bean id="transactionManager"
                   class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
                   <property name="dataSource" ref="dataSource" />
         </bean>
         <bean id="transactionTemplate"
                   class="org.springframework.transaction.support.TransactionTemplate">
                   <property name="transactionManager" ref="transactionManager" />
         </bean>

         <!-- ======================================================================== -->
         <!-- iBatis SQL map定义。 -->
         <!-- ======================================================================== -->
         <bean id="sqlMapClient" class="org.springframework.orm.ibatis.SqlMapClientFactoryBean">
                   <property name="dataSource" ref="dataSource" />
                   <property name="configLocation" value="classpath:META-INF/sqlmap/sqlmap-config.xml" />
         </bean>   
        
面对上面的配置,看下面的代码有什么问题:
                   try {
                            sqlMapClient.startTransaction();
                            //...do something
                            sqlMapClient.commitTransaction();
                   }
                   catch(Exception e) {
                            try {
                                     client.endTransaction();
                            } catch (Exception ex) {
                                     
                            }
                   }    
            
表面上没有问题,错!问题很大~~~看下面SqlMapClientFactoryBean源代码
import com.ibatis.sqlmap.engine.transaction.external.ExternalTransactionConfig;
public class SqlMapClientFactoryBean implements FactoryBean<SqlMapClient>, InitializingBean {
         //...省略其它
         private Class transactionConfigClass = ExternalTransactionConfig.class;
         
         public void afterPropertiesSet() throws Exception {
         //...
                   try {
                            //读取配置的ibatis映射
                            this.sqlMapClient = ...;

                            if (this.dataSource != null) {
                                     //这个地方关键的很,实例化了ExternalTransactionConfig,事务的提交取决这里。这里实际实例化的是ExternalTransactionConfig对象,而这个对象的内容,请看下面
                                     TransactionConfig transactionConfig = (TransactionConfig) this.transactionConfigClass.newInstance();
                                     DataSource dataSourceToUse = this.dataSource;
                                     if (this.useTransactionAwareDataSource && !(this.dataSource instanceof TransactionAwareDataSourceProxy)) {
                                               dataSourceToUse = new TransactionAwareDataSourceProxy(this.dataSource);
                                     }
                                     transactionConfig.setDataSource(dataSourceToUse);
                                     transactionConfig.initialize(this.transactionConfigProperties);
                                     //将事务配置应用到sqlMapClient
                                     applyTransactionConfig(this.sqlMapClient, transactionConfig);
                            }
                   }
                  //....
         }
}

再看下ExternalTransactionConfig代码:
public class ExternalTransactionConfig extends BaseTransactionConfig {

  private boolean defaultAutoCommit = false;
  private boolean setAutoCommitAllowed = true;
  //这里是spring启动事务调用的方法
  public Transaction newTransaction(int transactionIsolation) throws SQLException, TransactionException {
    return new ExternalTransaction(dataSource, defaultAutoCommit, setAutoCommitAllowed, transactionIsolation);
  }
  //...省略
}

再看ExternalTransaction:
public class ExternalTransaction implements Transaction {
  //...其它省略
  //ibatis默认使用外部事务提交的时候是空实现!回滚也是。
  public void commit() throws SQLException, TransactionException {
  }

  public void rollback() throws SQLException, TransactionException {
  }
}

到此真相大白,事务没有任何作用~~
也就是说如果使用spring集成管理ibatis,ibatis的事务将完全交由外部spring进行管理,ibatis不作为!

为什么有时候似乎数据库里面也插入了数据?哦,请看下面的属性配置:
<property name="defaultAutoCommit" value="true or false" />

这个属性的配置起了关键作用,如果配置为true,会自行提交,这也就不难解释为什么有数据了,而一旦配置成false,数据却一条也没有了~•~•

猜你喜欢

转载自sd-zyl.iteye.com/blog/1724863
今日推荐