MyBatis-Plus 核心功能详解:条件构造器、Service 封装与批量优化实践(黑马springcloud微服务课程)(day2)

MyBatis-Plus 核心功能详解:条件构造器、Service 封装与批量优化实践

在日常开发中,简单的基于 id 的 CRUD 并不能满足复杂业务需求。MyBatis-Plus 在 BaseMapper 的基础上,提供了条件构造器(Wrapper)通用 Service 层封装 以及高效批量处理能力,可以极大提升开发效率与代码可维护性。本文将系统总结这些核心能力,并结合实际示例进行说明。
上一节课的内容:MyBatis-Plus 快速入门与常用注解、配置总结

📚 目录(点击跳转对应章节)

一、条件构造器(Wrapper)
[二、QueryWrapper 与 UpdateWrapper 的使用](#二、QueryWrapper 与 UpdateWrapper 的使用)
[三、LambdaQueryWrapper 与 LambdaUpdateWrapper](#三、LambdaQueryWrapper 与 LambdaUpdateWrapper)
[四、自定义 SQL 与 Wrapper 结合使用](#四、自定义 SQL 与 Wrapper 结合使用)
[五、Service 层封装(IService & ServiceImpl)](#五、Service 层封装(IService & ServiceImpl))
[六、基于 Lambda 的动态条件查询](#六、基于 Lambda 的动态条件查询)
[七、LambdaUpdate 实现复杂业务更新](#七、LambdaUpdate 实现复杂业务更新)
八、批量新增性能优化
九、总结


一、条件构造器(Wrapper)

在 MyBatis-Plus 中,除了新增操作外,修改、删除、查询 都需要 WHERE 条件。BaseMapper 不仅支持基于 id 的操作,还支持通过 Wrapper 条件构造器实现复杂 SQL。

1. Wrapper 体系结构

  • Wrapper:条件构造的顶层抽象类
  • AbstractWrapper:提供所有 WHERE 条件的通用构造方法
  • QueryWrapper:在 AbstractWrapper 基础上扩展了 select,用于指定查询字段
  • UpdateWrapper:在 AbstractWrapper 基础上扩展了 set,用于构建 SET 语句

二、QueryWrapper 与 UpdateWrapper 的使用

1. QueryWrapper 查询示例

需求 :查询用户名中包含 o,且余额大于等于 1000 的用户。

java 复制代码
QueryWrapper<User> wrapper = new QueryWrapper<User>()
        .select("id", "username", "info", "balance")
        .like("username", "o")
        .ge("balance", 1000);

List<User> users = userMapper.selectList(wrapper);

2. QueryWrapper 更新示例

需求 :将用户名为 Jack 的用户余额修改为 2000。

java 复制代码
QueryWrapper<User> wrapper = new QueryWrapper<User>()
        .eq("username", "Jack");

User user = new User();
user.setBalance(2000);

userMapper.update(user, wrapper);

3. UpdateWrapper:基于原值更新字段

需求:对 id 为 1、2、4 的用户,余额统一扣减 200。

对应 SQL:

sql 复制代码
UPDATE user SET balance = balance - 200 WHERE id IN (1,2,4);

使用 UpdateWrapper#setSql

java 复制代码
UpdateWrapper<User> wrapper = new UpdateWrapper<User>()
        .setSql("balance = balance - 200")
        .in("id", List.of(1L, 2L, 4L));

userMapper.update(null, wrapper);

三、LambdaQueryWrapper 与 LambdaUpdateWrapper

1. 解决字符串魔法值问题

QueryWrapperUpdateWrapper 需要手写字段名字符串,不利于维护。MyBatis-Plus 提供了 Lambda Wrapper,通过方法引用自动解析字段名。

2. LambdaQueryWrapper 示例

java 复制代码
QueryWrapper<User> wrapper = new QueryWrapper<>();
wrapper.lambda()
        .select(User::getId, User::getUsername, User::getInfo, User::getBalance)
        .like(User::getUsername, "o")
        .ge(User::getBalance, 1000);

List<User> users = userMapper.selectList(wrapper);

四、自定义 SQL 与 Wrapper 结合使用

1. Wrapper + 注解 SQL

当业务不允许在 Service 层直接拼 SQL,可将 SQL 定义在 Mapper 中,并使用 Wrapper 生成条件。

java 复制代码
@Update("UPDATE user SET balance = balance - #{money} ${ew.customSqlSegment}")
void deductBalanceByIds(@Param("money") int money,
                        @Param("ew") QueryWrapper<User> wrapper);

调用方式:

java 复制代码
QueryWrapper<User> wrapper = new QueryWrapper<User>()
        .in("id", List.of(1L, 2L, 4L));

userMapper.deductBalanceByIds(200, wrapper);

2. 多表关联查询

MyBatis-Plus 不直接支持多表查询,但可通过 自定义 SQL + Wrapper 条件实现。

java 复制代码
QueryWrapper<User> wrapper = new QueryWrapper<User>()
        .in("u.id", List.of(1L, 2L, 4L))
        .eq("a.city", "北京");

Mapper:

java 复制代码
@Select("SELECT u.* FROM user u INNER JOIN address a ON u.id = a.user_id ${ew.customSqlSegment}")
List<User> queryUserByWrapper(@Param("ew") QueryWrapper<User> wrapper);

五、Service 层封装(IService & ServiceImpl)

MyBatis-Plus 提供了通用的 Service 接口 IService,以及默认实现 ServiceImpl,封装了常见业务方法:

  • save / saveBatch / saveOrUpdate
  • remove / update
  • get / list / count / page
  • lambdaQuery / lambdaUpdate

1. 自定义 Service

java 复制代码
public interface IUserService extends IService<User> {
    void deductBalance(Long id, Integer money);
}

实现类:

java 复制代码
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User>
        implements IUserService {
}

六、基于 Lambda 的动态条件查询

1. 动态查询条件实体

java 复制代码
public class UserQuery {
    private String name;
    private Integer status;
    private Integer minBalance;
    private Integer maxBalance;
}

2. lambdaQuery 链式查询

java 复制代码
List<User> users = userService.lambdaQuery()
        .like(query.getName() != null, User::getUsername, query.getName())
        .eq(query.getStatus() != null, User::getStatus, query.getStatus())
        .ge(query.getMinBalance() != null, User::getBalance, query.getMinBalance())
        .le(query.getMaxBalance() != null, User::getBalance, query.getMaxBalance())
        .list();

这种写法等价于 MyBatis 的 <if> 动态 SQL,代码更简洁、可读性更强。


七、LambdaUpdate 实现复杂业务更新

需求:扣减余额后,如果余额为 0,则将用户状态修改为冻结。

java 复制代码
lambdaUpdate()
        .set(User::getBalance, remainBalance)
        .set(remainBalance == 0, User::getStatus, 2)
        .eq(User::getId, id)
        .eq(User::getBalance, user.getBalance())
        .update();

这种方式可以实现 SET 部分的动态拼接,非常适合复杂更新场景。


八、批量新增性能优化

1. saveBatch 原理分析

MyBatis-Plus 的 saveBatch 本质是 PreparedStatement 批量执行 ,但默认情况下,数据库仍会执行多条 INSERT 语句。

2. MySQL 批处理 SQL 合并优化

通过开启 MySQL 驱动参数:

yaml 复制代码
spring:
  datasource:
    url: jdbc:mysql://127.0.0.1:3306/mp?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&rewriteBatchedStatements=true

即可将多条 INSERT 合并为一条多值 SQL:

sql 复制代码
INSERT INTO user (...) VALUES (...), (...), (...);

开启后,批量插入性能可获得数量级提升。


九、总结

MyBatis-Plus 在传统 MyBatis 的基础上,提供了:

  • 强大的条件构造器(Wrapper / LambdaWrapper)
  • 通用 Service 层封装,减少模板代码
  • Wrapper + 自定义 SQL 的灵活扩展能力
  • lambdaQuery / lambdaUpdate 简化复杂业务逻辑
  • 批量操作的性能优化手段

在实际项目中,合理使用 Wrapper + Service 封装 + 批量优化参数,可以显著提升开发效率与系统性能,是企业级项目中非常值得掌握的一套技术方案。

相关推荐
阿里云云原生2 天前
MSE Nacos Prompt 管理:让 AI Agent 的核心配置真正可治理
微服务·云原生
阿里云云原生2 天前
阿里云微服务引擎 MSE 及 API 网关 2026 年 1 月产品动态
微服务
追风筝的人er2 天前
企业管理系统如何实现自定义首页与千人千面?RuoYi Office 给出了完整方案
vue.js·spring boot·spring cloud
麦聪聊数据2 天前
统一 Web SQL 平台如何收编企业内部的“野生数据看板”?
数据库·sql·低代码·微服务·架构
莫寒清3 天前
Mybatis的插件原理
面试·mybatis
云司科技codebuddy3 天前
技术支持过硬Trae核心代理
大数据·运维·python·微服务
莫寒清3 天前
MyBatis 中动态 SQL 的作用
面试·mybatis
吹晚风吧3 天前
实现一个mybatis插件,方便在开发中清楚的看出sql的执行及执行耗时
java·sql·mybatis
码云数智-大飞3 天前
像写 SQL 一样搜索:dbVisitor 如何用 MyBatis 范式颠覆 ElasticSearch 开发
sql·elasticsearch·mybatis
递归尽头是星辰3 天前
微服务事务分级治理:从 Seata 全模式到 TDSQL 实战
微服务·云原生·架构·分布式事务·事务分级治理