返回

Mybatis ExecutorType.BATCH 使用详解:提升 SQL 性能

java

使用Mybatis ExecutorType.BATCH类型累积SQL语句

在Mybatis中,ExecutorType.BATCH类型允许累积多个SQL语句,并在适当的时候一次性发送到数据库,从而提高性能。

累积语句机制

  • 批处理队列: ExecutorType.BATCH类型打开会话时,会创建一个批处理器,该批处理器负责将SQL语句累积到队列中。
  • 刷新语句: 通过调用flushStatements()方法,Mybatis将队列中的所有语句一次性发送到数据库。

常见的误区

在使用ExecutorType.BATCH时,可能会遇到一些误区,导致语句无法正确累积:

  • 误区一:自动生成键
    • 如果SQL语句包含获取自动生成键的函数(如SELECT LAST_INSERT_ID()),Mybatis会在语句执行后立即向数据库发送请求。
  • 误区二:缓存刷新
    • 如果SQL语句更新了数据库数据,Mybatis会在语句执行后刷新缓存。
  • 误区三:手动刷新
    • 调用SqlSession.commit()SqlSession.rollback()也会触发语句刷新。

解决方法

  • 避免在SQL语句中使用自动生成键函数。
  • 在需要时手动刷新缓存(使用SqlSession.clearCache()方法)。
  • 在事务提交或回滚时,显式调用SqlSession.commit()SqlSession.rollback()

修改后的测试代码

public static void main(String[] args) {
    try (SqlSession sqlSession = DBConfig.getSessionFactory().openSession(ExecutorType.BATCH, true)) {
        TestMapper mapper = sqlSession.getMapper(TestMapper.class);

        // 累积4条插入语句
        mapper.save(new TestEntity(UUID.randomUUID().toString()));
        mapper.save(new TestEntity(UUID.randomUUID().toString()));
        mapper.save(new TestEntity(UUID.randomUUID().toString()));
        mapper.save(new TestEntity(UUID.randomUUID().toString()));

        // 手动刷新缓存
        sqlSession.clearCache();

        // 一次性刷新所有累积的语句
        List<BatchResult> batchResults = sqlSession.flushStatements();
        System.out.println("批处理结果:" + batchResults);
    } catch (Exception exception) {
        exception.printStackTrace();
    }
}

通过修改代码,我们手动刷新缓存,避免了在每个语句执行后发送请求,从而正确使用了ExecutorType.BATCH类型。

常见问题解答

  1. 为什么使用ExecutorType.BATCH
    • 减少网络开销,提高性能。
  2. 如何识别SQL语句需要刷新缓存?
    • 它们更新了数据库数据。
  3. 为什么自动生成键会导致问题?
    • Mybatis需要立即发送请求以获取键值。
  4. 除了手动刷新缓存之外,还有什么方法可以触发语句刷新?
    • 提交或回滚事务。
  5. ExecutorType.BATCH类型有哪些局限性?
    • 无法处理需要获取自动生成键的SQL语句。