在看iBatis的文档时,其描述的典型批处理语句如下:
try {sqlMap.startTransaction();sqlMap.startBatch();// … execute statements in betweenint rowsUpdated = sqlMap.executeBatch(); //optionalsqlMap.commitTransaction();} finally {sqlMap.endTransaction();}
这段语句,如果由iBatis自己来管理事务,相信大家没有使用任何的疑虑。但是,如果已经由Spring来托管事务,这段语句是不是有问题呢????
其实,我开始的时候这种疑问是非常强烈的,所以,有时我会这样写:sqlMap.startBatch();// … execute statements in betweenint rowsUpdated = sqlMap.executeBatch(); //optional
但是在运行时发现,批语句根本不起作用,后来查看源代码才知道:iBatis不管事务由谁来管理,批处理的方式是完全一致的!
那么sqlMap.startTransaction();sqlMap.commitTransaction();sqlMap.endTransaction();这三个语句难道不会对全局事务有任何影响吗??答案是:没有任何影响!
相信大家将Spring与IBatis集成时,都会使用如下的方式:
<bean id="sqlMapClient" class="org.springframework.orm.ibatis.SqlMapClientFactoryBean"> <property name="configLocation"> <value>classpath:sqlMapConfig-${database.type}.xml</value> </property> <property name="dataSource" ref="dataSource" /> </bean>查看SqlMapClientFactoryBean的源码,发现
……
private Class transactionConfigClass = ExternalTransactionConfig.class;
……
public void afterPropertiesSet() throws Exception {
……
TransactionConfig transactionConfig = (TransactionConfig) this.transactionConfigClass.newInstance();
……
}
……
也就是说,TransactionConfig 的类型是ExternalTransactionConfig。在运行时,ExternalTransactionConfig会构造出ExternalTransaction!
查看ExternalTransaction的源码,会发现rollback()和commit()方法不做任何事情!至此,我们就会明白:当Spring与iBatis集成时,iBatis的事务处理语句对全局事务不会有任何的影响!
结论:无论在何种情况之下,请放心大胆的使用iBatis文档中的调用方式,结果总是正确的!
实际上,你还可以通过继承SqlMapClientDaoSupport,以如下的方式进行处理:
getSqlMapClientTemplate().execute(new SqlMapClientCallback() { public Object doInSqlMapClient(SqlMapExecutor executor) throws SQLException { executor.startBatch(); executor.update("insertSomething", "myParamValue"); executor.update("insertSomethingElse", "myOtherParamValue"); executor.executeBatch(); return null; } });
