最近遇见了一个需要批量插入的操作,没办法只好又来看看了哟,话说好久都没认真研究过技术方面的东西了。由于spring3.0.5还没有集成mybatis3,所以只能使用mybatis官方自带的与spring3集成的jar包,叫mybatis-spring-1.0.0.jar。记得以前以前看过在spring+ibatis2时的批量插入代码,大概样式如下:
@Override
public void addArea(final List<Area> list){
this.getSqlMapClientTemplate().execute(new SqlMapClientCallback(){
@Override
public Object doInSqlMapClient(SqlMapExecutor executor)
throws SQLException {
executor.startBatch();
int batch = 0;
for(Area area:list){
executor.insert("area_addArea", area);
batch++;
if(batch==500){ //500条时批量插入一次
executor.executeBatch();
batch=0;
}
}
executor.executeBatch();
return null;
}
});
}
上面代码是通过回调函数手动进行批量插入,总体来说,来是比较简单的。
但是在mybatis-spring-1.0.0.jar中,并没有this.getSqlSession.execute(..)之类的方式,所以通过回调的方式也就不太可行了。在网上找到了这篇文章:
http://www.cnblogs.com/xcch/articles/2042298.html
上面这篇文章基本上说得比较清楚了,但是它并没有说怎么与spring3集成的,于是本人试着去弄一下怎么会spring集成的这个功能。mybatis-spring-1.0.0有个官方的文档,有英文的也有中文的,使用起来基本上与spring+ibatis2的思路是差不多的,即继承SqlSessionDaoSupport这个类,然后将sqlSessionTemplate注入此类的子类即可。然而批量处理时sqlSession是通过sessionFactory.openSession(ExecutorType.BATCH,false)得到的,而SqlSessionDaoSupport中通过getSqlSession()获得的sqlSession并没有可以获得SqlSessionFactory的方法,即org.apache.ibatis.session.SqlSession没有返回SqlSessionFactory的方法,不过实现了SqlSession的SqlSessionTemplate有此方法,因此只需要修改SqlSessionDaoSupport类,让其返回SqlSessionTemplate即可:
public class SqlSessionTemplateDaoSupport extends DaoSupport {
private SqlSessionTemplate sqlSession;
@Autowired(required = false)
public final void setSqlSessionFactory(SqlSessionFactory sqlSessionFactory) {
if (!this.externalSqlSession) {
this.sqlSession = new SqlSessionTemplate(sqlSessionFactory);
}
}
public final SqlSession getBatchSqlSession() {
return new SqlSessionTemplate(this.sqlSession.getSqlSessionFactory(),ExecutorType.BATCH);
// return sqlSession.getSqlSessionFactory().openSession(executorType, false);
}
...
可以看到新实现的SqlSessionTemplateDaoSupport类只是将返回类弄sqlSession的类型改成了SqlSessionTemplate,通过构造方法可以看出其实它本来就是SqlSessionTemplate类型的。需要注意的是上面构造sqlSession时是通过SqlSessionTemplate(this.sqlSession.getSqlSessionFactory(),ExecutorType.BATCH);来创建的,而不通过sqlSession.getSqlSessionFactory().openSession(executorType, false)来创建的。如果通过后者来创建需要手动来提交事务,即手动sqlSession.commit()。
而通过SqlSessionTemplate则不需要,因为SqlSessionTemplate中sqlSession的执行是需要通过SqlSessionInterceptor拦截的,这个动态拦截器会在执行方法后自己执行sqlSession.commit()方法。