mybatis批量插入提效关键在于三层协同:启用executortype.batch复用preparedstatement、mysql需配置rewritebatchedstatements=true驱动级合并sql、配合手写多值insert语法,并调优jdbc.batch_size、分批提交及连接池参数。

MyBatis 中批量插入提效的关键,不是加个 foreach 就完事,而是要让 SQL 真正“批量”发出去——减少网络往返、复用连接、合并语句、避开逐条提交。核心配置围绕 JDBC 层、MyBatis 执行器、SQL 语法三层面展开。
启用 BATCH 执行器模式
这是最基础也最关键的一步。默认 ExecutorType 是 SIMPLE,每次 insert 都新建 Statement;改用 BATCH 后,MyBatis 会缓存多条 SQL 到同一个 PreparedStatement,最后统一提交。
- 代码中显式开启:SqlSession sqlSession = sqlSessionFactory.openSession(ExecutorType.BATCH);
- 或全局配置(推荐):
<setting name="defaultExecutorType" value="BATCH"></setting> - 注意:必须手动调用 sqlSession.commit(),否则数据不会落库
开启 JDBC 驱动级批量重写(MySQL 必配)
仅配 MyBatis 的 BATCH 不够——MySQL 官方驱动默认把 batch 拆成单条执行。需在数据库连接 URL 中启用重写:
- 添加参数:
rewriteBatchedStatements=true - 完整示例:
jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=utf8&rewriteBatchedStatements=true - 效果:驱动自动将 100 条 INSERT 转为
INSERT INTO t(...) VALUES(...),(...),...单条语句,性能跃升数倍
配合数据库原生批量语法写 XML
对不支持 rewriteBatchedStatements 的数据库(如 PostgreSQL、SQL Server),或需要更精细控制时,直接手写多值 INSERT:
- Mapper 接口定义:
void batchInsert(@Param("list") List<user> list);</user> - XML 中用
<foreach></foreach>拼接:INSERT INTO user (name, age) VALUES <foreach collection="list" item="u" separator=","> (#{u.name}, #{u.age}) </foreach> - 注意:values 后不能换行或空格过多,避免生成非法 SQL;字段数过多时需留意 MySQL 的 max_allowed_packet 限制
调优配套参数与实践细节
光配对还不行,几个关键参数和习惯决定最终效果:
- jdbc.batch_size:设为 500–2000(视单条数据大小调整),太大易 OOM,太小起不到批量作用
-
关闭自动提交:BATCH 模式下务必
sqlSession.setAutoCommit(false),否则每条仍单独提交 - 分批处理大列表:插入 10 万条时,不要一次性传入,按 1000 条/批拆分,避免内存溢出和 SQL 过长
-
连接池配置:HikariCP 建议增大
connection-timeout和max-lifetime,避免批量期间连接中断











