<!-- ======================================================================== --> <!-- 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,数据却一条也没有了~•~•