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次

posted @ 2019-08-11 16:39  ◆╮提笔写惆怅?  阅读(416)  评论(0编辑  收藏  举报