ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

03-MyBatisPlus之DQL编程控制

2022-06-27 20:32:31  阅读:195  来源: 互联网

标签:03 MyBatisPlus user 查询 User 条件 DQL 属性 userLambdaQueryWrapper


三、DQL编程控制

3.1、条件查询方式

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

3.1.1、条件查询

  • 方式一:按条件查询

    • 查询年龄大于18岁的用户

    • @Test
          // 条件查询----查询年龄大于18的数据
          public void selectByCondition() {
              // 1. 创建一个条件对象
              QueryWrapper<User> userQueryWrapper = new QueryWrapper<>();
      
              // 2. 设置条件
              userQueryWrapper.gt("age", 18);
      
              // 3. 调用mapper对象
              List<User> userList = userMapper.selectList(userQueryWrapper);
      
              userList.forEach(user -> {
                  log.info("" + user);
              });
      
          }
      
  • 方式二:lamba格式按条件查询(推荐)

    • 推荐原因

      • 在创建一个普通QueryWrapper对象的时候,直接设置条件的时候传递的是("列名", 列值),考虑到列名有可能写错或者不存在而在运行时候报错。就可以使用LambdaQueryWarpper对象来实现
    • 查询年龄大于18的用户

    •     @Test
          // 条件查询---查询年龄大于18的数据(lambda方式)
          public void selectByConditionWithLambda() {
              LambdaQueryWrapper<User> userLambdaQueryWrapper = new LambdaQueryWrapper<>();
      
              userLambdaQueryWrapper.gt(User::getAge, 18);
      
              List<User> userList = userMapper.selectList(userLambdaQueryWrapper);
      
              userList.forEach(user -> {
                  log.info("" + user);
              });
          }
      

3.1.2、组合条件

  • 并且关系(and)

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

    •     @Test
          // 组合条件查询---并且关系
          public void selectByMultiConditionWithLambda() {
              // 1. 创建条件对象
              LambdaQueryWrapper<User> userLambdaQueryWrapper = new LambdaQueryWrapper<>();
      
              // 2. 设置条件
              userLambdaQueryWrapper.lt(User::getAge, 30);
              userLambdaQueryWrapper.gt(User::getAge, 10);
      
              // 调用mapper对象,实现查询
              List<User> userList = userMapper.selectList(userLambdaQueryWrapper);
      
              userList.forEach(user -> {
                  log.info(user + "");
              });
          }
      
  • 或者关系(or)

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

    •     @Test
          // 组合条件查询---或者关系
          public void selectByMultiOrConditionWithLambda() {
              // 1. 创建条件对象
              LambdaQueryWrapper<User> userLambdaQueryWrapper = new LambdaQueryWrapper<>();
      
              // 2. 设置条件
              userLambdaQueryWrapper.gt(User::getAge, 30);
              userLambdaQueryWrapper.or();
              userLambdaQueryWrapper.lt(User::getAge, 10);
      
              // 调用mapper对象,实现查询
              List<User> userList = userMapper.selectList(userLambdaQueryWrapper);
      
              userList.forEach(user -> {
                  log.info(user + "");
              });
          }
      

3.1.3、NULL值处理

  • 问题导入

    • 假设现在有一个搜索场景,在多条件查询中,有部分条件的值为空应该要怎么解决?
  • 方式一:if语句控制条件追加

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

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

    •     @Test
          // 根据年龄搜索,分别最小年龄,最大年龄,名字, 只要三个变量中任何一个不为空都要作为条件查询
          public void selectByMultiNullConditionWithLambda() {
              // 1. 模拟搜索条件
              Integer maxAge = null;
              Integer minAge = 20;
              String name = "K";
      
              // 2. 创建条件对象
              LambdaQueryWrapper<User> userLambdaQueryWrapper = new LambdaQueryWrapper<>();
      
              // 3. 设置条件对象的参数
      
              // 如果最大年龄不为空
              // ge,le 分别是大于等于,小于等于;gt、lt分别是大于,小于
              if (maxAge != null) {
                  userLambdaQueryWrapper.le(User::getAge, maxAge);
              }
      
              // 如果最小年龄不为空
              if (minAge != null) {
                  userLambdaQueryWrapper.ge(User::getAge, minAge);
              }
      
              // 如果姓名不为空
              if (name != null) {
                  userLambdaQueryWrapper.like(User::getName, name);
              }
      
              // 4. 调用mapper对象实现查询
              List<User> userList = userMapper.selectList(userLambdaQueryWrapper);
      
              for (User user : userList) {
                  log.info("" + user);
              }
          }
      
  • 方式二:条件参数控制

    • 跟方式一差不多,只不过格式上有点点不一样

    •     @Test
          // 根据年龄搜索,分别最小年龄,最大年龄,名字, 只要三个变量中任何一个不为空都要作为条件查询
          public void selectByMultiNullConditionWithLambda2() {
              // 1. 模拟搜索条件
              Integer maxAge = null;
              Integer minAge = 20;
              String name = "K";
      
              // 2. 创建条件对象
              LambdaQueryWrapper<User> userLambdaQueryWrapper = new LambdaQueryWrapper<>();
      
              // 3. 设置条件对象的参数
      
              // 如果最大年龄不为空
              // ge,le 分别是大于等于,小于等于;gt、lt分别是大于,小于
              userLambdaQueryWrapper.le(maxAge != null, User::getAge, maxAge);
      
              // 如果最小年龄不为空
              userLambdaQueryWrapper.ge(minAge != null, User::getAge, minAge);
      
              // 如果姓名不为空
              userLambdaQueryWrapper.like(name != null, User::getName, name);
      
              // 4. 调用mapper对象实现查询
              List<User> userList = userMapper.selectList(userLambdaQueryWrapper);
      
              for (User user : userList) {
                  log.info("" + user);
              }
          }
      

3.2、查询投影--设置【查询字段、分组、分页】

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

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

  • 使用SELECT 列名1, 列名2...的方法,查询的结果封装成实体类,其他属性为NULL值

  • @Test
        // 查询实体类中的部分字段值 (id,name,age)
        public void selectByPartColumnWithLambda() {
            // 1. 创建条件对象
            LambdaQueryWrapper<User> userLambdaQueryWrapper = new LambdaQueryWrapper<>();
    
            // 2. 设置条件
            userLambdaQueryWrapper.select(User::getId, User::getName, User::getAge);
    
            // 3. 调用mapper对象,查询数据
            List<User> userList = userMapper.selectList(userLambdaQueryWrapper);
    
            for (User user : userList) {
                log.info("" + user);
            }
        }
    

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

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

  • 需求

    • 按性别进行分组,统计每组的人数。只显示统计的人数和性别这两个字段
  • 使用QueryWrapper包装对象的select方法

    • 原因:因为是查询模型类中未定义的属性,使用Lambda表达式的话,就需要实体类有相对应的属性才可以赋值给条件对象,所以这里就不再使用Lambda的方式

    • 同时,因为包含实体类中未定义的属性,所以在使用mapper对象的查询方法的时候也不能使用selectList而是使用selecMaps

    •     @Test
          // 查询结果中包含实体类中没有定义的属性(统计人数,性别)
          public void selectByNonPartColumn() {
              // 1. 创建条件对象
              QueryWrapper<User> userQueryWrapper = new QueryWrapper<>();
      
              // 2. 设置查询条件
              // select gender count(*) from user group by gender;
              userQueryWrapper.select("gender", "count(*)");
              userQueryWrapper.groupBy("gender");
      
              // 3. 调用mapper对象实现查询
              List<Map<String, Object>> mapList = userMapper.selectMaps(userQueryWrapper);
      
              for (Map<String, Object> map : mapList) {
                  log.info(map + "");
              }
      
          }
      

3.3、查询条件

  • 我们可以回想一下多条件查询有哪些组合?
    • ①、范围匹配(>、=、between)
    • ②、模糊匹配(like)
    • ③、空判断(null)
    • ④、包含性判断(in)
    • ⑤、分组(group)
    • ⑥、排序(order)
    • ...

3.3.1、区间匹配

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

  •     // 区间匹配(查询年龄10岁到30岁这个范围)
        @Test
        public void selectByInterval() {
            // 1. 创建条件对象
            LambdaQueryWrapper<User> userLambdaQueryWrapper = new LambdaQueryWrapper<>();
    
            // 2. 设置条件
    
            // le、ge匹配
    //        userLambdaQueryWrapper.ge(User::getAge, 10);    // 大于等于10
    //        userLambdaQueryWrapper.le(User::getAge, 30);    // 小于等于30
    
            // betwwen匹配
            userLambdaQueryWrapper.between(User::getAge, 10, 30);
    
            // 3. 调用mapper对象,实现查询
            List<User> userList = userMapper.selectList(userLambdaQueryWrapper);
    
            for (User user : userList) {
                log.info("" + user);
            }
        }
    

3.3.2、模糊匹配

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

  • // 模糊匹配
        @Test
        public void selectByFuzzy() {
            // 1. 创建条件对象
            LambdaQueryWrapper<User> userLambdaQueryWrapper = new LambdaQueryWrapper<>();
    
            // 2. 设置条件
            // like %J%
    //        userLambdaQueryWrapper.like(User::getName, "J");
            // like %J
    //        userLambdaQueryWrapper.likeLeft(User::getName, "J");
            // like J%
            userLambdaQueryWrapper.likeRight(User::getName, "J");
    
    
            // 3. 调用mapper对象
            List<User> userList = userMapper.selectList(userLambdaQueryWrapper);
    
            for (User user : userList) {
                log.info("" + user);
            }
        }
    

3.3.3、分组查询聚合函数

  • 统计报表(按性别分组,然后计数分组的后的数量)

  • // 分组查询聚合函数
        @Test
        public void selectByGroupAndCount() {
            // 1. 创建条件对象
            QueryWrapper<User> userQueryWrapper = new QueryWrapper<>(); // 这里不用Lambda的原因是查询结果有一个不属于实体类
    
            // 2. 设置条件
            userQueryWrapper.select("gender", "count(*) as sum");
    
            userQueryWrapper.groupBy("gender");
    
            // 3. 调用mapper对象,实现查询
            List<Map<String, Object>> maps = userMapper.selectMaps(userQueryWrapper);
    
            for (Map<String, Object> map : maps) {
                log.info("" + map);
            }
        }
    

3.3.4、排序和limit

  • 需求

    • 显示年龄最大的5个用户
  • 说明

    • ①、对年龄进行降序排序
    • ②、仅获取前5条数据
    • 也可以考虑2.2节,MyBatis-plus分页操作
  • last()方法说明

    • 无视优化规则直接拼接到sql的最后(有sql注入的风险,谨慎使用)
    • PS:只能调用一次,多次调用以最后一次为准
  •     // order和limit:显示年龄最大的5个用户
        @Test
        public void selectByOrderAndLimit() {
            // 1. 创建条件对象
            LambdaQueryWrapper<User> userLambdaQueryWrapper = new LambdaQueryWrapper<>();
    
            // 2. 设置条件
            userLambdaQueryWrapper.orderByDesc(User::getAge);   // desc降序排序   asc升序排序
    
            userLambdaQueryWrapper.last("limit 0, 5");
    
            // 3. 调用mapper对象,实现查询
            List<User> users = userMapper.selectList(userLambdaQueryWrapper);
    
            for (User user : users) {
                log.info("" + user);
            }
    
        }
    

3.4、字段映射与表名映射问题导入

  • 如果表的字段和实体类的属性不对应而出现的问题

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

  • 测试步骤

    • 1、修改表的列名(后续测试结束再修改回来即可)

      • -- 修改表的列名
        ALTER TABLE `user` CHANGE `password` `pwd` VARCHAR(20);
        
    • 2、执行查询出现异常,报不知道的列password

    • 3、在模型类属性上方,使用@TableField属性注解,通过value属性,设置当前属性对应的数据库表中的字段值;要不就老老实实更改实体类中的属性

      • 解决方式1
      • 解决方式2
    • 4、再次执行查询,可以正常运行

      • SQL语句如下所示

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

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

  • 测试步骤
    • 1、在实体类中添加新的属性Integer online
    • 2、再次执行查询,发现报错
  • 解决办法
    • 最简单直接不过就是把这个新增的直接删掉
    • 如果在不得不需要该属性的情况下
      • 可以在模型类属性上方,使用@TableField注解,通过exist属性,设置属性在数据库表字段中是否存在,默认为true。此属性无法与value同时使用
  • 再次执行查询
    • 没有报错,但是online的值为空

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

  • 需求
    • password这个字段不查询
  • 解决办法
    • 在模型类属性上方,使用@TableField注解,通过select属性设置该属性是否参与查询,此属性与select()映射配置不冲突
    • SQL语句如下所示
      • SELECT id,name,gender,age,tel FROM user
    • 因为该字段不参与查询,返回给实体类的时候自然是null

3.4.4、问题四:表名和实体类名不同

  • 测试步骤

    • 1、修改表名,模拟表名和实体类名不同

      • ALTER TABLE user RENAME TO tbl_user
        
    • 2、执行查询,运行出现异常

  • 解决办法

    • 在模型类上方,使用@TableName注解,通过value属性,设置当前类对应的数据库表名称;当然直接修改类名也不是不可以,只不过可能会引起连锁反应
    • 再次执行查询语句,发现可以成功运行,执行的SQL语句如下所示
      • SELECT id,name,gender,password,age,tel FROM tbl_user

标签:03,MyBatisPlus,user,查询,User,条件,DQL,属性,userLambdaQueryWrapper
来源: https://www.cnblogs.com/OnlyOnYourself-lzw/p/16417427.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有