问小白 wenxiaobai
资讯
历史
科技
环境与自然
成长
游戏
财经
文学与艺术
美食
健康
家居
文化
情感
汽车
三农
军事
旅行
运动
教育
生活
星座命理

MyBatisPlus条件查询详解

创作时间:
作者:
@小白创作中心

MyBatisPlus条件查询详解

引用
CSDN
1.
https://m.blog.csdn.net/weixin_53961667/article/details/139429480

MyBatisPlus条件查询

MyBatisPlus是一个MyBatis的增强工具,旨在简化开发、提高效率。本文将详细介绍MyBatisPlus的条件查询功能,包括查询条件方式、组合条件、NULL值处理、查询投影、查询条件、字段映射与表名映射等多个方面。

1. 查询条件方式

MyBatisPlus将书写复杂的SQL查询条件进行了封装,使用编程的形式完成查询条件的组合。

方式一:按条件查询

查询年龄大于18岁的用户

@Test
void testQueryWrapper() {
    //1. 创建查询条件封装对象,可以指定泛型
    QueryWrapper<User> wrapper = new QueryWrapper();
    //2.字段age大于18
    wrapper.gt("age", 18);
    //3.执行查询
    List<User> users = userMapper.selectList(wrapper);
    //4.输出结果
    users.forEach(System.out::println);
}

方式二:lambda格式按条件查询(推荐)

查询年龄小于10的用户

@Test
void testLambdaQueryWrapper() {
    //1.创建lambda查询包装器,支持泛型
    LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper();
    //2. 使用lambda参数,相当于调用 user -> user.getAge()方法,获取列名
    wrapper.le(User::getAge, 10);
    //3.查询
    List<User> users = userMapper.selectList(wrapper);
    //4.输出结果
    users.forEach(System.out::println);
}

2. 组合条件

并且关系(and)

查询年龄小于30岁,而且大于10岁的用户

@Test
void testAnd() {
    //并且关系
    LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>();
    //支持链式写法
    wrapper.lt(User::getAge, 30).gt(User::getAge, 10);
    List<User> userList = userMapper.selectList(wrapper);
    System.out.println(userList);
}

生成的SQL语句

SELECT id,name,gender,password,age,tel FROM user WHERE (age < ? AND age > ?)

或者关系(or)

查询年龄小于10岁或者大于30岁的用户

@Test
void testOr() {
    LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>();
    //或者关系:小于10岁或者大于30岁
    wrapper.lt(User::getAge, 10).or().gt(User::getAge, 30);
    List<User> userList = userMapper.selectList(wrapper);
    System.out.println(userList);
}

生成的SQL语句

SELECT id,name,gender,password,age,tel FROM user WHERE (age < ? OR age > ?)

3. NULL值处理

在多条件查询中,有条件的值为空应该怎么解决?

  • 如果最小年龄不为空,则查询大于这个年龄的用户
  • 如果最大年龄不为空,则查询小于这个年龄的用户

if语句控制条件追加

@Test
void testNullValue() {
    Integer minAge = 10;  //将来有用户传递进来,此处简化成直接定义变量了
    Integer maxAge = null;  //将来有用户传递进来,此处简化成直接定义变量了
    LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>();
    if (minAge != null) {
        wrapper.gt(User::getAge, minAge);  //大于
    }
    if (maxAge != null) {
        wrapper.lt(User::getAge, maxAge);  //小于
    }
    List<User> userList = userMapper.selectList(wrapper);
    userList.forEach(System.out::println);
}

条件参数控制

@Test
void testCondition() {
    Integer minAge=10;  //将来有用户传递进来,此处简化成直接定义变量了
    Integer maxAge=null;  //将来有用户传递进来,此处简化成直接定义变量了
    LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>();
    //参数1:如果表达式为true,那么查询才使用该条件,也支持链式编程
    wrapper.gt(minAge != null, User::getAge, minAge);
    wrapper.lt(maxAge != null, User::getAge, maxAge);
    //查询
    List<User> userList = userMapper.selectList(wrapper);
    //输出
    userList.forEach(System.out::println);
}

4. 查询投影-设置【查询字段、分组】

查询结果包含模型类中部分属性

查询所有用户,只显示id, name, age三个属性,不是全部列。

使用
select(列名...)
方法,查询的结果如果封装成实体类,则只有这三个属性有值,其它属性为NULL

@Test
void testSameColumn() {
    LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>();
    //查询所有用户,只显示id, name, age三个属性,不是全部列
    wrapper.select(User::getId, User::getName, User::getAge);
    List<User> userList = userMapper.selectList(wrapper);
    System.out.println(userList);
}

SQL语句

SELECT id,name,age FROM user

查询结果包含模型类中未定义的属性

如果查询结果包含模型类中未定义的属性,则将每个元素封装成Map对象。

需求:按性别进行分组,统计每组的人数。只显示统计的人数和性别这两个字段

使用QueryWrapper包装对象的select方法

@Test
void testCountGender() {
    //使用QueryWrapper包装对象
    QueryWrapper<User> wrapper = new QueryWrapper<>();
    //查询2列:人数, 性别。 将聚合函数定义别名做为Map中的键
    wrapper.select("count(*) as count, gender");
    //按sex分组
    wrapper.groupBy("gender");
    //这里的查询方法使用selectMaps
    List<Map<String, Object>> list = userMapper.selectMaps(wrapper);
    list.forEach(System.out::println);
}

5. 查询条件

多条件查询有哪些组合?

  • 范围匹配(> 、 = 、between)
  • 模糊匹配(like)
  • 空判定(null)
  • 包含性匹配(in)
  • 分组(group)
  • 排序(order)
  • ……

购物设定价格区间、户籍设定年龄区间(le ge匹配 或 between匹配)

LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<User>();
//范围查询 lt le gt ge eq between
wrapper.between(User::getAge, 10, 30);
List<User> userList = userMapper.selectList(wrapper);
System.out.println(userList);

查信息,搜索新闻(非全文检索版:like匹配)

/**
 * 需求: 查询姓张的用户
 *    select * from user where name like '张%'
 */
@Test
public void testFindByLike(){
    LambdaQueryWrapper<User> lambdaQueryWrapper = new LambdaQueryWrapper<>();
    lambdaQueryWrapper.likeRight(User::getName,"张");
    List<User> userList = userMapper.selectList(lambdaQueryWrapper);
    userList.forEach(System.out::println);
}

统计报表(分组查询聚合函数)

QueryWrapper<User> qw = new QueryWrapper<User>();
qw.select("gender", "count(*) as nums");
qw.groupBy("gender");
List<Map<String, Object>> maps = userMapper.selectMaps(qw);
System.out.println(maps);

排序和limit

题目:显示年龄最大的5个用户

说明:

①:提示:对年龄进行降序排序
②:仅获取前5条数据(提示:使用分页功能控制数据显示数量)

last()方法的说明:

无视优化规则直接拼接到 sql 的最后(有sql注入的风险,请谨慎使用),注意只能调用一次,多次调用以最后一次为准

/**
 * 需求: 查询年龄大于18岁的前三位
 *      select * from user where age>18 order by age desc limit 3;
 *
 */
@Test
public void testFindByLimit(){
    LambdaQueryWrapper<User> lambdaQueryWrapper = new LambdaQueryWrapper<>();
    lambdaQueryWrapper.gt(User::getAge,18).orderByDesc(User::getAge).last("limit 3");
    List<User> userList = userMapper.selectList(lambdaQueryWrapper);
    userList.forEach(System.out::println);
}

生成的SQL

SELECT id,name,gender,password,age,tel FROM user WHERE (age > ?) ORDER BY age DESC limit 3

6. 字段映射与表名映射问题导入

问题一:表字段与编码属性设计不同步

解决办法:

  • 在模型类属性上方,使用@TableField属性注解,通过==value==属性,设置当前属性对应的数据库表中的字段关系。

生成的SQL语句,自动给pwd这一列定义了别名为password, 从而给实体类属性password封装数据

SELECT id,name,gender,pwd AS password,age,tel FROM user

问题二:编码中添加了数据库中未定义的属性

解决方法:

  • 在模型类属性上方,使用@TableField注解,通过exist属性,设置属性在数据库表字段中是否存在,默认为true。此属性无法与value同时使用。

不会去查询online

User(id=4, name=NewBoy, gender=男, password=123456, age=19, tel=12345678910, online=null)

问题三:某些字段和属性不参与查询

需求:password这个字段不查询

  • 在模型类属性上方,使用@TableField注解,通过select属性:设置该属性是否参与查询。此属性与select()映射配置不冲突。

查询的SQL语句中不包含pwd字段

SELECT id,name,gender,age,tel FROM user WHERE id=?

实体类的password属性中没有值

User(id=4, name=NewBoy, gender=男, password=null, age=19, tel=12345678910, online=null)

问题四:表名与实体类名不同

解决方法:

  • 模型类上方,使用@TableName注解,通过value属性,设置当前类对应的数据库表名称。

@Data
@TableName("tbl_user")
public class User {
}

查询生成的SQL语句

SELECT id,name,gender,age,tel FROM tbl_user WHERE id=?
© 2023 北京元石科技有限公司 ◎ 京公网安备 11010802042949号