先看段经典的ibatis spring配置,注意我的配置中没有配置spring的声明式事务:
面对上面的配置,看下面的代码有什么问题:
表面上没有问题,错!问题很大~~~看下面SqlMapClientFactoryBean源代码
再看下ExternalTransactionConfig代码:
再看ExternalTransaction:
到此真相大白,事务没有任何作用~~
也就是说如果使用spring集成管理ibatis,ibatis的事务将完全交由外部spring进行管理,ibatis不作为!
为什么有时候似乎数据库里面也插入了数据?哦,请看下面的属性配置:
这个属性的配置起了关键作用,如果配置为true,会自行提交,这也就不难解释为什么有数据了,而一旦配置成false,数据却一条也没有了~•~•
<!-- ======================================================================== -->
<!-- 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,数据却一条也没有了~•~•