mybatis mysql批量更新生效需同时满足:url加rewritebatchedstatements=true、mybatis配置batch执行器;xml中推荐case when单语句方式,并分批控制在500–2000条以内。

MyBatis 在 MySQL 中做批量更新时,仅靠 XML 里写 <foreach></foreach> 或调用 MyBatis-Plus 的 updateBatch 是不够的。真正起效的关键一步:必须在数据库连接 URL 中启用 rewriteBatchedStatements=true。
MySQL 连接 URL 必须加这个参数
这是 JDBC 驱动层的开关,不加它,批量更新实际仍被拆成单条执行——每条都走完整解析、权限校验、日志刷盘流程,性能几乎无提升。
- 正确写法(Spring Boot
application.yml):
spring:
datasource:
url: jdbc:mysql://localhost:3306/mydb?useUnicode=true&characterEncoding=utf8&rewriteBatchedStatements=true&serverTimezone=Asia/Shanghai
- 驱动版本要求:MySQL 8.0+ 推荐用
mysql-connector-java:8.0.33+;5.x 版本需 ≥ 5.1.13 - 注意:该参数对
INSERT、UPDATE、DELETE全部有效,不只是插入
MyBatis 层要配 BATCH 执行器
让 MyBatis 把多条 update() 调用暂存,再统一交给 JDBC 批处理接口。
- 全局配置(推荐,
mybatis-config.xml):
- 代码中手动控制(更灵活):
SqlSession sqlSession = sqlSessionFactory.openSession(ExecutorType.BATCH);
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
// 执行多次 update
mapper.update(user1);
mapper.update(user2);
// ...
sqlSession.commit(); // 必须显式提交
XML 中写批量 UPDATE 的两种方式
根据场景选一种,但都要配合上面两个配置才真正高效:
-
方式一:多语句拼接(需同时开
allowMultiQueries=true)
适用于字段更新逻辑差异大、或需逐条控制条件的场景:
UPDATE user SET name = #{item.name}, age = #{item.age} WHERE id = #{item.id}
-
方式二:CASE WHEN 单语句(推荐,无需
allowMultiQueries)
性能更高、兼容性更好,适合主键明确、更新字段一致的场景:
UPDATE user
SET name = CASE id
WHEN #{item.id} THEN #{item.name}
ELSE name END,
age = CASE id
WHEN #{item.id} THEN #{item.age}
ELSE age END
WHERE id IN
#{item.id}
分批处理避免超限和 OOM
即使配置全了,一次性传入 5 万条更新数据仍可能触发 MySQL 的 max_allowed_packet 或 JVM 内存溢出。
- 建议单批控制在 500–2000 条之间(视单条 SQL 长度调整)
- Java 侧边循环、边刷新:
int batchSize = 1000;
for (int i = 0; i mapper.update(userList.get(i));
if ((i + 1) % batchSize == 0) {
sqlSession.flushStatements();
sqlSession.clearCache();
}
}
sqlSession.flushStatements();
sqlSession.commit();
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











