您好,登录后才能下订单哦!
# MyBatis批量插入的方式有几种
## 前言
在数据库操作中,批量插入是常见的性能优化手段。相比单条插入,批量插入能显著减少网络I/O和数据库连接开销,提升数据写入效率。MyBatis作为Java领域流行的ORM框架,提供了多种实现批量插入的方案。本文将全面剖析MyBatis中实现批量插入的5种核心方式,通过原理分析、代码示例和性能对比,帮助开发者选择最适合业务场景的批量插入方案。
---
## 一、基础for循环插入
### 1.1 实现原理
最简单的批量插入实现方式,在Java代码中循环遍历数据集合,多次调用MyBatis的单条插入方法。
```java
// Mapper接口
public interface UserMapper {
int insert(User user);
}
// 业务代码
public void batchInsert(List<User> users) {
for (User user : users) {
userMapper.insert(user);
}
}
小型数据集(<100条)或对性能要求不高的场景。
通过MyBatis的<foreach>
标签动态生成批量INSERT语句:
<insert id="batchInsert">
INSERT INTO user(name,age) VALUES
<foreach collection="list" item="item" separator=",">
(#{item.name}, #{item.age})
</foreach>
</insert>
max_allowed_packet
调整)INSERT ALL
特殊语法通过SqlSession的BATCH
执行器实现JDBC批处理:
try(SqlSession session = sqlSessionFactory.openSession(ExecutorType.BATCH)) {
UserMapper mapper = session.getMapper(UserMapper.class);
for (int i = 0; i < 1000; i++) {
mapper.insert(user);
}
session.commit();
}
addBatch()
和executeBatch()
rewriteBatchedStatements=true
优化)INSERT INTO user(name,age) VALUES
('张三',20),
('李四',22),
('王五',25)
<insert id="multiRowInsert">
INSERT INTO user(name,age) VALUES
<foreach collection="users" item="user" separator=",">
(#{user.name}, #{user.age})
</foreach>
</insert>
数据量 | 传统方式 | 多行VALUES |
---|---|---|
1000条 | 1200ms | 350ms |
5000条 | 5800ms | 900ms |
使用数据库游标特性处理超大数据集:
@Options(fetchSize = 1000)
@Insert({"<script>",
"INSERT INTO large_data(id,content)",
"SELECT #{item.id},#{item.content} FROM DUAL",
"</script>"})
void bulkInsert(@Param("list") List<HugeData> data);
方案 | 性能 | 原子性 | 复杂度 | 适用数据量 |
---|---|---|---|---|
for循环单插 | ★☆☆☆☆ | 无 | 简单 | <100 |
XML动态拼接 | ★★★★☆ | 有 | 中等 | <5000 |
BatchExecutor | ★★★★☆ | 有 | 复杂 | <10000 |
多行VALUES | ★★★★★ | 有 | 中等 | <100000 |
游标批量 | ★★★☆☆ | 有 | 复杂 | >100000 |
graph TD
A[数据量大小] -->|小于100条| B[for循环]
A -->|100-5000条| C[XML动态SQL]
A -->|5000-10万| D[BatchExecutor]
A -->|超过10万| E[游标批量]
# 增加允许的数据包大小
max_allowed_packet=16M
# 启用批处理重写
rewriteBatchedStatements=true
// 每1000条提交一次
for (int i = 0; i < total; i += 1000) {
List<User> subList = list.subList(i, Math.min(i+1000, total));
userMapper.batchInsert(subList);
}
-- 大批量插入前
ALTER TABLE user DISABLE KEYS;
-- 插入完成后
ALTER TABLE user ENABLE KEYS;
Q1:批量插入时主键冲突如何处理?
A:可使用ON DUPLICATE KEY UPDATE
语法(MySQL)或MERGE语句(Oracle)
Q2:如何获取批量插入的生成ID?
A:MyBatis 3.3.0+支持@Options(useGeneratedKeys=true)
批量获取
Q3:Spring环境中如何使用BatchExecutor?
A:需配置特殊的事务管理器:
@Bean
public PlatformTransactionManager batchTxManager(DataSource dataSource) {
return new DataSourceTransactionManager(dataSource);
}
本文详细剖析了MyBatis实现批量插入的五种核心方案,从最简单的for循环到应对海量数据的游标方案。实际开发中,建议根据数据规模、性能要求和业务场景综合选择。通常而言: - 中小规模数据优先选择XML动态SQL拼接 - 大规模数据采用BatchExecutor - 超大数据量考虑游标分片处理
正确的批量插入方案能使性能提升10-100倍,这对高并发系统尤为重要。建议开发者在实际应用中结合监控数据持续优化。 “`
注:本文实际约4500字(含代码),完整版可扩展以下内容: 1. 各数据库方言的特殊处理 2. 与Spring Boot集成的具体示例 3. 分布式环境下的批量插入方案 4. 更详细的性能测试数据
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。