在 MyBatis 中批量插入几千条数据时,通常有以下几种方式可以提高性能,避免一次性插入大量数据导致性能问题。常见的批量插入方法有通过 <foreach>
标签、批量执行 ExecutorType.BATCH
和自定义批量插入方法。
方法 1:使用 <foreach>
标签进行批量插入
MyBatis 提供了 <foreach>
标签,可以用来执行批量插入操作。下面是一个批量插入的例子:
1. SQL 映射文件中的 <insert>
配置
<insert id="batchInsert" parameterType="java.util.List">
INSERT INTO your_table (column1, column2, column3)
VALUES
<foreach collection="list" item="item" index="index" separator=",">
(#{item.column1}, #{item.column2}, #{item.column3})
</foreach>
</insert>
collection="list"
:指向要插入的数据集合,通常是一个 List。item="item"
:指代集合中的每一个元素。separator=","
:指定每一条插入记录之间用逗号分隔。
2. Mapper 接口中的方法
public interface YourMapper {
void batchInsert(List<YourEntity> entities);
}
3. 调用 Mapper 方法进行批量插入
List<YourEntity> entities = new ArrayList<>();
// 填充实体列表
yourMapper.batchInsert(entities);
优点:
- 简单明了,容易理解。
- 适合数据量较小(几百条数据)。
限制:
- 如果数据量非常大(几千条或更多),可能会导致 SQL 语句过长,超出数据库的查询长度限制。
方法 2:使用 ExecutorType.BATCH
执行批量插入
ExecutorType.BATCH
是 MyBatis 提供的批量执行功能,它能够将多条 SQL 语句打包成一个批次一起执行,能够有效提高性能。
1. 配置 SqlSessionFactory
首先,你需要配置 SqlSessionFactory
,并设置 ExecutorType.BATCH
:
SqlSessionFactory sqlSessionFactory = ...; // 获取 SqlSessionFactory
SqlSession session = sqlSessionFactory.openSession(ExecutorType.BATCH, false); // 使用批量执行模式
2. Mapper 接口和 XML 配置
<insert id="batchInsert" parameterType="java.util.List">
INSERT INTO your_table (column1, column2, column3)
VALUES
<foreach collection="list" item="item" index="index" separator=",">
(#{item.column1}, #{item.column2}, #{item.column3})
</foreach>
</insert>
3. 调用批量插入方法
List<YourEntity> entities = new ArrayList<>();
// 填充实体列表
YourMapper mapper = session.getMapper(YourMapper.class);
for (int i = 0; i < entities.size(); i++) {
mapper.batchInsert(entities.subList(i, Math.min(i + batchSize, entities.size())));
if (i % batchSize == 0 || i == entities.size() - 1) {
session.commit();
}
}
session.close();
4. 调整批次大小
- 批次大小(
batchSize
)根据具体情况进行调整,通常大小在 500 到 1000 之间。 - 批次大小过大可能会导致内存占用过高,过小则可能没有充分发挥批量插入的优势。
方法 3:使用自定义批量插入逻辑
如果需要更细粒度的控制,可以自定义批量插入的逻辑。例如,使用 MyBatis 提供的 SqlSession
对象的 insert()
方法多次调用插入语句,并在合适时机调用 commit()
。
示例代码:
public void batchInsert(List<YourEntity> entities) {
SqlSession session = sqlSessionFactory.openSession(ExecutorType.BATCH, false);
try {
YourMapper mapper = session.getMapper(YourMapper.class);
int batchSize = 500;
for (int i = 0; i < entities.size(); i++) {
mapper.batchInsert(Collections.singletonList(entities.get(i)));
// 每隔 batchSize 条提交一次
if (i % batchSize == 0 || i == entities.size() - 1) {
session.commit();
}
}
} finally {
session.close();
}
}
方法 4:批量插入时避免 flush()
和 commit()
在批量插入的过程中,如果每插入一定数量的数据就调用 flush()
和 commit()
,可能会影响性能。在批量插入时,可以将这两个操作的频率降低,控制在一个合理的范围内。
其他优化建议
- 数据库配置:确保数据库表的索引配置合理,避免索引过多或不必要的索引干扰插入性能。
- 连接池配置:如果应用程序使用了数据库连接池,确保连接池的配置足够高效。
- 事务控制:确保事务提交时机正确,避免频繁的提交操作。
所有评论(0)