Mybatis批量处理
可以通过全局配置文件指定默认的Executor开启批量处理模式:
<setting name="defaultExecutorType" value="BATCH"/>
如果在全局配置文件中指定的话BATCH模式的话,所有的其他不需要批量处理的sql,都默认使用了Batch模式,所以正常情况下在应该在获取sqlSession的时候指定使用Batch类型的Executor,而不应该在全局配置文件配置:
@Test
public void testBatch() throws IOException{
SqlSessionFactory sqlSessionFactory = getSqlSessionFactory();
//可以执行批量操作的sqlSession
SqlSession openSession = sqlSessionFactory.openSession(ExecutorType.BATCH);
long start = System.currentTimeMillis();
try{
EmployeeMapper mapper = openSession.getMapper(EmployeeMapper.class);
for (int i = 0; i < 10000; i++) {
mapper.addEmp(new Employee(UUID.randomUUID().toString().substring(0, 5), "b", "1"));
}
openSession.commit();
long end = System.currentTimeMillis();
System.out.println("执行时长:"+(end-start));//批量模式 执行时长4598,非批量模式 执行时长10200
}finally{
openSession.close();
}
}
很明显,批量模式插入有更高的效率,大概看看BatchExecutor的源码了解其原因:
@Override
public int doUpdate(MappedStatement ms, Object parameterObject) throws SQLException {
final Configuration configuration = ms.getConfiguration();
final StatementHandler handler = configuration.newStatementHandler(this, ms, parameterObject, RowBounds.DEFAULT, null, null);
final BoundSql boundSql = handler.getBoundSql();
final String sql = boundSql.getSql();
final Statement stmt;
//判断MappedStatement和sql语句是否和缓存的一致
if (sql.equals(currentSql) && ms.equals(currentStatement)) {
int last = statementList.size() - 1;
//获取上一次已经预编译过的PreparedStatement(主要优化)
stmt = statementList.get(last);
applyTransactionTimeout(stmt);
//设置sql参数
handler.parameterize(stmt);
BatchResult batchResult = batchResultList.get(last);
//保存每次传入的参数
batchResult.addParameterObject(parameterObject);
} else {//首次执行
//获取连接
Connection connection = getConnection(ms.getStatementLog());
//预编译sql,获取PreparedStatement
stmt = handler.prepare(connection, transaction.getTimeout());
//设置sql参数
handler.parameterize(stmt);
//缓存当前sql语句
currentSql = sql;
//缓存MappedStatement(代表增删改查标签的所有信息)
currentStatement = ms;
//保存PreparedStatement
statementList.add(stmt);
batchResultList.add(new BatchResult(ms, sql, parameterObject));
}
handler.batch(stmt);
return BATCH_UPDATE_RETURN_VALUE;
}
主要的差别:
批量模式:(预编译sql一次==>设置参数10000次===>执行1次)
非批量模式:每插入一条记录都要完整的执行(预编译sql==>设置参数==>执行)10000次