mybatis高效批量insert
时间: 2025-05-21 19:18:06 浏览: 18
### MyBatis 高效批量插入的实现方式
在实际项目开发中,MyBatis 的高效批量插入是一个常见的需求。以下是几种常用的实现方式及其特点:
#### 1. 使用 `foreach` 标签配合 SQL 的 `INSERT ... VALUES (...)`
这是最常见的一种批量插入方式,适用于大多数数据库环境。通过 `<foreach>` 标签遍历传入的集合参数,并将其映射为多条 `VALUES` 子句。
```xml
<insert id="batchInsert" parameterType="java.util.List">
INSERT INTO table_name (column1, column2, column3)
VALUES
<foreach collection="list" item="item" separator=",">
(#{item.column1}, #{item.column2}, #{item.column3})
</foreach>
</insert>
```
这种方式的优点在于简单易懂,适合中小规模的数据插入[^1]。然而需要注意的是,如果数据量过大可能导致 SQL 过长而超出数据库的最大长度限制。
---
#### 2. 利用 Oracle 的 `UNION ALL` 构造批量插入
针对 Oracle 数据库,可以利用 `UNION ALL` 将多个子查询组合成一条完整的插入语句。这种方法能够有效减少网络交互次数,从而提高性能。
```xml
<insert id="batchInsertWithUnionAll" parameterType="java.util.List">
INSERT INTO user(uuid, account, username, password)
SELECT A.uuid, A.account, A.username, A.password FROM (
<foreach collection="list" item="item" index="index" separator="UNION ALL">
SELECT #{item.uuid} uuid, #{item.account} account,
#{item.username} username, #{item.password} password FROM dual
</foreach>
) A
</insert>
```
此方法特别适合于需要自定义主键或其他复杂字段的情况[^3]。
---
#### 3. 使用 `ExecutorType.BATCH` 提升执行效率
除了调整 SQL 外,还可以修改 MyBatis 的执行器类型为 `BatchExecutor`,以启用 JDBC 批量操作模式。这可以通过设置全局配置或动态指定来完成。
```java
SqlSession sqlSession = sqlSessionFactory.openSession(ExecutorType.BATCH);
try {
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
for (User user : userList) {
mapper.insert(user); // 单次调用不会立即提交
}
sqlSession.commit(); // 统一提交事务
} finally {
sqlSession.close();
}
```
注意:当使用批处理时需关闭 `useGeneratedKeys=true` 参数,因为它可能引发兼容性问题[^2]。
---
#### 4. 应用 Oracle 的 `MERGE` 语句支持 Upsert 操作
对于既存在新增又可能存在更新的需求场景,推荐采用 Oracle 的 `MERGE` 语句。它允许在一个请求内判断目标表是否存在匹配记录并分别采取不同的动作(插入或更新)。
```xml
<insert id="mergeInsertOrUpdate" parameterType="java.util.List">
MERGE INTO target_table t
USING (
<foreach collection="list" item="record" separator="UNION ALL">
SELECT #{record.id} AS id, #{record.value} AS value FROM dual
</foreach>
) s
ON (t.id = s.id)
WHEN MATCHED THEN
UPDATE SET t.value = s.value
WHEN NOT MATCHED THEN
INSERT (id, value) VALUES (s.id, s.value)
</insert>
```
上述代码片段展示了如何结合循环结构生成动态子查询列表[^4]。
---
#### 性能优化建议
- **控制单批次大小**:避免一次性加载过多数据进入内存,通常每批次保持几千至几万条之间较为合理。
- **预编译 PreparedStatement**:确保每次仅创建一次物理连接上的 SQL 对象而非重复解析字符串形式命令。
- **监控资源消耗情况**:定期审查 CPU、I/O 和锁等待指标以便及时发现问题所在。
相关问题
阅读全文
相关推荐


















