Mybatis批量处理

Posted qzlcl

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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次

以上是关于Mybatis批量处理的主要内容,如果未能解决你的问题,请参考以下文章

Mybatis批量事务处理

Mybatis配置SQL批量处理

Mybatis批处理(批量查询,更新,插入)

Mybatis批处理(批量查询,更新,插入)

mybatis foreach批量处理

mybatis 批量操作数据