在数据库操作中,批量处理是提升系统吞吐量的关键手段。MyBatis-Plus 作为 MyBatis 的增强工具,通过封装 JDBC 原生能力与动态 SQL 技术,提供了灵活的批量插入和删除方案。本文将深入解析实则现机制,并通过实战代码说明使用方法与性能优化策略。
一、批量插入的实现与原理
1.1 基础实现:insertBatchSomeColumn方法
MyBatis-Plus 提供的 insertBatchSomeColumn 方法基于 JDBC 的 addBatch() 实现,其本质是将多个独立的 INSERT 语句打包发送到数据库执行:
List<User> userList = Arrays.asList(
new User("Alice", 22, "alice@example.com"),
new User("Bob", 28, "bob@example.com")
);
int rows = userMapper.insertBatchSomeColumn(userList);
执行原理:
- 遍历集合构建多个 INSERT INTO table (col1, col2) VALUES (?, ?) 语句
- 通过 PreparedStatement.addBatch() 缓存 SQL
- 调用 executeBatch() 一次性提交 效果分析:
- 优点:实现简单,兼容性好
- 缺点:实际执行仍是多条 SQL,网络传输开销大,性能有限
1.2 优化方案:单条多值插入
为解决基础方案的性能瓶颈,可通过自定义 SQL 实现真正的批量插入:
<insert id="insertBatch">
INSERT INTO user (name, age, email)
VALUES
<foreach collection="list" item="user" separator=",">
(#{user.name}, #{user.age}, #{user.email})
</foreach>
</insert>
执行原理:
- 生成单条 INSERT INTO … VALUES (…), (…), (…) 语句
- 通过一次网络请求完成多条数据插入 性能对比测试(1000条数据):
- | 方案 | 耗时(ms) | 数据库压力 |
- |——————–|————|————|
- | insertBatchSomeColumn | 1200 | 中 | | 自定义多值插入 | 300 | 低 |
1.3 分批次处理策略
针对超大数据量(如 10w+ 条),提议分批次处理:
public void batchInsert(List<User> dataList, int batchSize) {
int total = dataList.size();
for (int i = 0; i < total; i += batchSize) {
List<User> subList = dataList.subList(i, Math.min(i + batchSize, total));
userMapper.insertBatch(subList);
}
}
二、批量删除的实现与原理
2.1 基础实现:deleteBatchIds方法
MyBatis-Plus 提供的主键批量删除方法,底层通过 IN 语句实现:
List<Long> ids = Arrays.asList(1001L, 1002L, 1003L);
int rows = userMapper.deleteBatchIds(ids);
生成的 SQL:
DELETE FROM user WHERE id IN (1001, 1002, 1003)
执行原理:
- 构建 IN 条件语句
- 单次数据库交互完成删除 适用场景:
- 主键明确的小批量删除(提议控制在 1000 条以内)
2.2 自定义条件删除
通过 UpdateWrapper 实现复杂条件的批量删除:
UpdateWrapper<User> wrapper = new UpdateWrapper<>();
wrapper.eq("status", 0).lt("createTime", "2023-01-01");
userMapper.delete(wrapper);
生成的 SQL:
DELETE FROM user WHERE status = 0 AND create_time < '2023-01-01'
2.3 逻辑删除支持
若启用逻辑删除功能(通过 @TableLogic 注解),删除操作会自动转换为更新:
UPDATE user SET del_flag=1 WHERE id IN (1001, 1002, 1003)
三、性能优化与注意事项
3.1 JDBC 批处理优化
在使用 addBatch() 时,需配置数据库连接参数:
spring.datasource.url=jdbc:mysql://localhost:3306/db?rewriteBatchedStatements=true
该参数可将多条 INSERT 合并为 INSERT VALUES (),(),() 格式。
3.2 事务管理
批量操作提议在事务中执行:
@Transactional(rollbackFor = Exception.class)
public void batchProcess() {
userMapper.insertBatchSomeColumn(userList);
userMapper.deleteBatchIds(ids);
}
3.3 内存控制
- 单次批量操作数据量提议控制在 1000-5000 条
- 超大数据量采用分页 + 批量处理模式
- 使用 try-with-resources 管理资源
四、完整代码示例
Mapper 接口扩展
public interface UserMapper extends BaseMapper<User> {
int insertBatch(@Param("list") List<User> userList);
}
XML 映射文件
<!-- 批量插入 -->
<insert id="insertBatch">
INSERT INTO user (name, age, email)
VALUES
<foreach collection="list" item="user" separator=",">
(#{user.name}, #{user.age}, #{user.email})
</foreach>
</insert>
<!-- 批量删除 -->
<delete id="deleteBatch">
DELETE FROM user
WHERE id IN
<foreach collection="list" item="id" open="(" separator="," close=")">
#{id}
</foreach>
</delete>
Service 层调用
@Service
public class UserService {
@Autowired
private UserMapper userMapper;
public void batchInsertUsers(List<User> users) {
if (users.size() > 1000) {
throw new IllegalArgumentException("单次插入数据量不能超过1000条");
}
userMapper.insertBatch(users);
}
public void batchDeleteUsers(List<Long> ids) {
if (ids.size() > 1000) {
throw new IllegalArgumentException("单次删除数据量不能超过1000条");
}
userMapper.deleteBatchIds(ids);
}
}
五、总结
|
功能 |
推荐方案 |
最佳实践 |
|
批量插入 |
自定义多值 INSERT SQL |
控制单批数据量 + 启用 rewriteBatchedStatements |
|
批量删除 |
deleteBatchIds + IN |
小数据量主键删除 + 分页处理 |
|
超大数据量 |
分批次处理 |
每批 1000-5000 条 + 事务控制 |
通过合理使用 MyBatis-Plus 的批量操作功能,可显著提升数据库交互效率。在实际开发中,提议根据业务场景选择合适的实现方案,并结合性能监控持续优化。
© 版权声明
文章版权归作者所有,未经允许请勿转载。
相关文章
暂无评论...