MyBatis-Plus 批量插入与删除功能详解:原理、实现与性能优化

内容分享1周前发布
0 0 0

在数据库操作中,批量处理是提升系统吞吐量的关键手段。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);

执行原理:

  1. 遍历集合构建多个 INSERT INTO table (col1, col2) VALUES (?, ?) 语句
  2. 通过 PreparedStatement.addBatch() 缓存 SQL
  3. 调用 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 的批量操作功能,可显著提升数据库交互效率。在实际开发中,提议根据业务场景选择合适的实现方案,并结合性能监控持续优化。

© 版权声明

相关文章

暂无评论

您必须登录才能参与评论!
立即登录
none
暂无评论...