【MyBatis-Plus 条件构造器】全面解析 Wrapper

news/2025/1/8 6:06:39/

在 MyBatis-Plus 中, 条件构造器 是一个强大的工具,能够帮助我们灵活地构建 SQL 查询条件,而无需手写繁琐的 SQL 语句。本文将从基础到高级,带你全面了解条件构造器的使用方法及其链式构造能力。


一、什么是条件构造器?

条件构造器是 MyBatis-Plus 提供的 动态 SQL 拼接工具,主要用于生成 SQL 查询中的 WHERE 条件部分,支持动态拼接、链式调用以及条件逻辑控制

常见的条件构造器

  1. QueryWrapper:用于通用的条件查询。
  2. UpdateWrapper:用于更新操作的条件构造。
  3. LambdaQueryWrapperLambdaUpdateWrapper:使用 Lambda 表达式构造条件,避免直接写字段名称导致的拼写错误。

二、基础用法

常用方法一览

方法描述示例补充说明
eq等于.eq("status", 1)常用于精确匹配某个字段的值,例如查询某种状态的数据。
ne不等于.ne("status", 0)用于排除特定值的记录,例如排除状态为 0 的数据。
gt / ge大于 / 大于等于.gt("age", 18)可用于筛选范围,例如筛选 18 岁以上用户。
lt / le小于 / 小于等于.lt("age", 60)结合 gt,实现区间查询,例如 18-60 岁之间的用户。
like / notLike模糊查询 / 非模糊查询.like("name", "Tom")like 通常用于字符串匹配,例如姓名包含某字;notLike 用于排除模糊匹配的记录。
likeLeft / likeRight左 / 右模糊查询.likeLeft("name", "Tom") / .likeRight("name", "Tom")左模糊适用于以某个关键字结尾的情况,右模糊适用于以关键字开头的情况。
isNull / isNotNull字段是否为空 / 不为空.isNotNull("email")判断字段值是否存在,适用于有些字段可能为空值的情况,例如邮箱地址。
in / notIn在列表中 / 不在列表中.in("id", Arrays.asList(1, 2, 3)) / .notIn("id", Arrays.asList(4, 5))in 通常用于批量匹配多个条件,例如查询多个 ID 的记录。
between / notBetween在区间内 / 不在区间内.between("age", 18, 60)gtlt 更简洁,适用于范围筛选。
orderBy / orderByDesc排序.orderByDesc("create_time") / .orderByAsc("age")支持多字段排序,例如 .orderByAsc("age").orderByDesc("create_time")
groupBy分组.groupBy("status")通常与聚合函数结合使用,例如统计每种状态的记录数。
having分组后的筛选条件.groupBy("status").having("count(*) > 5")适用于对分组结果的进一步筛选,例如过滤分组中记录数少于 5 的组。
last手动拼接 SQL 片段.last("LIMIT 1")手动拼接自定义的 SQL 片段,但需谨慎使用,确保不会引起 SQL 注入风险。
exists / notExists子查询条件.exists("SELECT 1 FROM user WHERE user.id = order.user_id")适用于判断某记录是否存在,结合子查询使用。
apply自定义 SQL 条件.apply("DATE(create_time) = {0}", "2025-01-01")

1. QueryWrapper 的基本操作

示例:构造简单查询条件

java">QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("status", 1).like("name", "Tom").orderByDesc("create_time");List<User> users = userMapper.selectList(queryWrapper);

生成的 SQL:

SELECT * FROM user WHERE status = 1 AND name LIKE '%Tom%' ORDER BY create_time DESC;

2. LambdaQueryWrapper 的基本操作

使用 Lambda 表达式构建查询条件,避免字段名硬编码导致的错误,可以传入一个函数式接口来动态获取查询的字段等。

示例:构造条件

java">LambdaQueryWrapper<User> lambdaWrapper = new LambdaQueryWrapper<>();
lambdaWrapper.eq(User::getStatus, 1).like(User::getName, "Tom");List<User> users = userMapper.selectList(lambdaWrapper);

优点

  • 避免直接使用字符串字段名
  • 修改实体类字段名时,条件构造器能自动适配。

3. UpdateWrapper 的基本操作

UpdateWrapper 用于构造更新条件,可以同时设置更新内容和条件

示例:构造更新条件

java">UpdateWrapper<User> updateWrapper = new UpdateWrapper<>();
updateWrapper.eq("id", 1).set("status", 2);userMapper.update(null, updateWrapper);

生成的 SQL:

UPDATE user SET status = 2 WHERE id = 1;

三、高级用法

1. 链式调用的高级操作

条件构造器支持链式调用,能大幅提升代码的可读性。

示例:根据条件动态添加查询
java">String name = "Tom";
Integer age = null;QueryWrapper<User> wrapper = new QueryWrapper<>();
wrapper.eq(name != null, "name", name).ge(age != null, "age", age);List<User> users = userMapper.selectList(wrapper);

只会生成:

SELECT * FROM user WHERE name = 'Tom';

注意eq 等方法的第一个参数为布尔值,控制条件是否拼接。


2. 嵌套查询条件

使用 andor 结合嵌套条件,构造复杂查询。

示例:嵌套条件
java">QueryWrapper<User> wrapper = new QueryWrapper<>();
wrapper.and(w -> w.eq("status", 1).or().eq("status", 2)).like("name", "Tom");List<User> users = userMapper.selectList(wrapper);

生成的 SQL:

SELECT * FROM user WHERE (status = 1 OR status = 2) AND name LIKE '%Tom%';

3. LambdaQueryWrapper 的自定义排序

LambdaQueryWrapper 支持条件排序,可以动态调整排序字段。

示例:动态排序
java">boolean orderByAge = true;LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>();
wrapper.eq(User::getStatus, 1).orderBy(orderByAge, true, User::getAge);List<User> users = userMapper.selectList(wrapper);

说明orderBy 的第一个参数控制是否应用排序(指定一个条件),第二个参数控制升序还是降序,第三个参数指定根据哪一列排序。


4. 使用条件构造器分页查询

与分页插件结合,条件构造器可以轻松实现分页查询。

示例:分页查询
java">IPage<User> page = new Page<>(1, 10); // 第1页,每页10条
QueryWrapper<User> wrapper = new QueryWrapper<>();
wrapper.ge("age", 18).le("age", 60);IPage<User> result = userMapper.selectPage(page, wrapper);

生成的 SQL:

SELECT * FROM user WHERE age >= 18 AND age <= 60 LIMIT 0, 10;

四、链式条件构造器 ChainWrapper

MyBatis-Plus 提供了链式条件构造器,使查询与更新操作更加简洁流畅,主要包括 QueryChainWrapper / LambdaQueryChainWrapperUpdateChainWrapper / LambdaUpdateChainWrapper。以下我们结合查询与更新操作详细讲解其使用方式。


1. 查询的链式构造器

MyBatis-Plus 提供 query()lambdaQuery() 方法用于查询操作的链式调用,最终通过调用特定方法(如 .list().one())返回结果。

返回值方法

以下是 QueryChainWrapper / LambdaQueryChainWrapper 中常见的调用链终点方法及其返回值:

  • .list():返回符合条件的所有记录,类型为 List<T>
  • .one():返回符合条件的单条记录,类型为 T。如果有多条记录,则会抛出异常。
  • .count():返回符合条件的记录数,类型为 long
  • .exists():判断是否有符合条件的记录,返回 boolean
  • .map():返回查询结果的 Map 表示,通常适用于单表查询。
java">// 获取符合条件的所有记录
List<User> users = userService.lambdaQuery().eq(User::getStatus, 1).orderByDesc(User::getCreateTime).list();// 获取符合条件的单条记录
User user = userService.lambdaQuery().eq(User::getId, 1).one();// 获取符合条件的记录总数
long count = userService.lambdaQuery().eq(User::getStatus, 1).count();// 判断是否存在符合条件的记录
boolean exists = userService.lambdaQuery().eq(User::getName, "Tom").exists();

【注意】

  • 如果查询条件返回多条记录而使用 .one(),会抛出异常,因此建议对主键或唯一字段使用该方法。
  • .exists() 的效率较高,可用于快速判断。
基本查询
  • QueryChainWrapper(基于字段名):
java">List<User> users = userService.query().eq("status", 1).like("name", "Tom").orderByDesc("create_time").list();
  • LambdaQueryChainWrapper(基于 Lambda 表达式):
java">List<User> users = userService.lambdaQuery().eq(User::getStatus, 1).like(User::getName, "Tom").orderByDesc(User::getCreateTime).list();
动态条件查询

通过链式构造器可以动态拼接查询条件,避免不必要的条件参与 SQL 构造:

java">String name = null;
Integer age = 25;List<User> users = userService.lambdaQuery().like(name != null, User::getName, name).eq(age != null, User::getAge, age).list();

namenull 时,生成的 SQL 会自动忽略对应条件:

SELECT * FROM user WHERE age = 25;
分页查询

结合分页对象可以快速实现分页功能:

java">IPage<User> page = userService.lambdaQuery().eq(User::getStatus, 1).orderByDesc(User::getCreateTime).page(new Page<>(1, 10));

2. 更新的链式构造器

对于更新操作,MyBatis-Plus 提供了 update()lambdaUpdate() 方法,支持基于链式条件构造更新数据。

基本更新
  • 使用 LambdaUpdateChainWrapper 更新指定条件的数据:
java">boolean updated = userService.lambdaUpdate().eq(User::getStatus, 1).set(User::getName, "Tom Updated").set(User::getAge, 30).update();

生成的 SQL

UPDATE user SET name = 'Tom Updated', age = 30 WHERE status = 1;
动态字段更新

通过布尔值控制是否更新某些字段,实现动态更新逻辑:

java">String name = null;
Integer age = 30;boolean updated = userService.lambdaUpdate().set(name != null, User::getName, name).set(age != null, User::getAge, age).eq(User::getStatus, 1).update();

如果 namenull,生成的 SQL 将忽略对 name 的更新:

UPDATE user SET age = 30 WHERE status = 1;
批量更新

通过 in 条件轻松实现批量更新:

java">boolean updated = userService.lambdaUpdate().in(User::getId, Arrays.asList(1, 2, 3)).set(User::getStatus, 2).update();

生成的 SQL

UPDATE user SET status = 2 WHERE id IN (1, 2, 3);

五、最佳实践

  1. 优先使用 LambdaQueryWrapper,能避免字段名硬编码的潜在错误,更适合复杂的查询场景。

  2. 善用动态拼接, 利用条件构造器的布尔控制参数,可以根据条件动态生成 SQL,减少不必要的拼接逻辑。

  3. 分页查询与排序结合,在大数据量场景中,结合分页插件和条件构造器能显著提升查询效率。

  4. 封装公共查询逻辑,对于复杂的查询条件,可以将条件构造封装为方法,方便重复使用。例如:

    java">public QueryWrapper<User> buildActiveUserQuery() {QueryWrapper<User> wrapper = new QueryWrapper<>();wrapper.eq("status", 1).isNotNull("email");return wrapper;
    }
    

六、总结

MyBatis-Plus 的条件构造器为我们提供了构建 SQL 条件的强大工具。从基础的查询条件到复杂的嵌套逻辑,再到链式调用和动态条件,条件构造器可以极大提升开发效率。同时,灵活使用分页、排序等高级功能,可以让你的查询逻辑更清晰、更高效。在日常开发中,掌握这些技巧,将让你在 MyBatis-Plus 的使用中更加得心应手!


http://www.ppmy.cn/news/1560660.html

相关文章

vim、watch、cp和mv

一、vim使用技巧 vim主配置文件&#xff1a;/etc/vimrc &#xff08;对所有用户都生效&#xff09; vim子配置文件&#xff1a;vim ~/.vimrc (只对当前用户生效&#xff09; 可写入&#xff1a; set nu 显示行号 ts2 tab键长度为两个空格&#xff08;默认为8个空格…

【Rust练习】26.Package and Crate

练习题来自&#xff1a;https://practice-zh.course.rs/crate-module/crate.html 建议在命令行下操作完成本节内容&#xff0c;Windows 11/10 首选 Windows 终端&#xff0c;好看&#xff0c;支持渲染中文字体&#xff0c;缺点是功能太少了&#xff1b;其次推荐 mobaxterm&…

pytorch中nn.Conv2d详解及参数设置原则

文章目录 基础参数1. in_channels (输入通道数)2. out_channels (输出通道数)3. kernel_size (卷积核大小)4. stride (步幅)5. padding (填充)6. dilation (膨胀)7. groups (分组卷积)8. bias (偏置) 如何设置参数&#xff1f;1. **in_channels 和 out_channels&#xff08;输入…

5G终端串口AT命令 FM650 常用命令

5G终端串口AT命令 FM650 常用命令 5G终端串口AT命令 FM650 常用命令 #状态查询 MODULE_PORT/dev/ttyUSB0echo -e "ATE0\r\n" > $MODULE_PORT echo -e "ATGTUSBMODE?\r\n" > $MODULE_PORT echo -e "ATGTRAT?" > $MODULE_PORT ec…

【JMeter详解】

JMeter详解 Apache JMeter 是一个开源的、100%纯Java应用程序&#xff0c;设计用于负载测试和性能测量。它最初是为测试Web应用程序而设计的&#xff0c;但后来扩展到其他测试功能。JMeter可以用来对静态和动态资源&#xff08;如静态文件、Servlets、Perl脚本、Java对象、数据…

多分类的损失函数

在多分类任务中,常用的损失函数能够衡量模型输出的类别分布与目标类别之间的差异,帮助模型学习更准确的分类能力。以下是多分类任务中常用的损失函数: 1. 交叉熵损失(Cross-Entropy Loss) 公式: CrossEntropyLoss = − 1 N ∑ i =

logback日志文件多环境配置路径

项目中遇到问题&#xff0c;springboot项目 本地jar包部署到现场后&#xff0c;经常遇到现场的日志存放的路径会更改&#xff0c;经过查阅&#xff0c;有两种方式&#xff0c;下面简单说明一下。 一、第一种 启动jar包时 添加参数 --logging.configF:\hgtest\config\logback.x…

cut-命令详解

一、命令 1.cut列截取命令 cut命令的默认分隔符是制表符 2.参数&#xff1a; -f 列号 #提取第几列-d 分隔符 #按照指定分隔符分割列-c 字符范围 #不依赖分隔符来区分列&#xff0c;而是通过字符范围&#xff08;行首为0&#xff09;来进行字段提取。“n-”表…