写点什么

[MyBatisPlus]DQL 编程控制①(条件查询)

作者:fake smile by
  • 2022 年 9 月 15 日
    黑龙江
  • 本文字数:3585 字

    阅读完需:约 12 分钟

条件查询

结构还是前文的结构这里不再多赘述。

解决日志冗长的问题

  • 不过测试的时候,控制台打印的日志比较多,速度有点慢而且不利于查看运行结果,所以接下来我们把这个日志处理下:

  • 取消初始化 spring 日志打印,resources 目录下添加 logback.xml,名称固定,内容如下:


    <?xml version="1.0" encoding="UTF-8"?>    <configuration>    </configuration>
复制代码


>**说明**:logback.xml的配置内容,不是我们学习的重点,如果有兴趣可以自行百度查询。
复制代码


  • 取消 MybatisPlus 启动 banner 图标


  • application.yml 添加如下内容:


    # mybatis-plus日志控制台输出    mybatis-plus:      configuration:        log-impl: org.apache.ibatis.logging.stdout.StdOutImpl      global-config:        banner: off # 关闭mybatisplus启动图标
复制代码


  • 取消 SpringBoot 的 log 打印


  • application.yml 添加如下内容:


    spring:      main:        banner-mode: off # 关闭SpringBoot启动图标(banner)
复制代码


解决控制台打印日志过多的相关操作可以不用去做,一般会被用来方便我们查看程序运行的结果。

构建条件查询

在进行查询的时候,我们的入口是在 Wrapper 这个类上,因为它是一个接口,所以我们需要去找它对应的实现类,关于实现类也有很多,说明我们有多种构建查询条件对象的方式:



  1. 先来看第一种:==QueryWrapper==


@SpringBootTestclass Mybatisplus02DqlApplicationTests {
@Autowired private UserDao userDao; @Test void testGetAll(){ QueryWrapper qw = new QueryWrapper(); qw.lt("age",18); List<User> userList = userDao.selectList(qw); System.out.println(userList); }}
复制代码


  • lt: 小于(<) ,最终的 sql 语句为


  SELECT id,name,password,age,tel FROM user WHERE (age < ?)
复制代码


第一种方式介绍完后,有个小问题就是在写条件的时候,容易出错,比如 age 写错,就会导致查询不成功


  1. 接着来看第二种:==QueryWrapper 的基础上使用 lambda==


@SpringBootTestclass Mybatisplus02DqlApplicationTests {
@Autowired private UserDao userDao; @Test void testGetAll(){ QueryWrapper<User> qw = new QueryWrapper<User>(); qw.lambda().lt(User::getAge, 10);//添加条件 List<User> userList = userDao.selectList(qw); System.out.println(userList); }}
复制代码


  • User::getAget,为 lambda 表达式中的,类名::方法名,最终的 sql 语句为:


SELECT id,name,password,age,tel FROM user WHERE (age < ?)
复制代码


注意:构建 LambdaQueryWrapper 的时候泛型不能省。


此时我们再次编写条件的时候,就不会存在写错名称的情况,但是 qw 后面多了一层 lambda()调用


  1. 接着来看第三种:==LambdaQueryWrapper==


@SpringBootTestclass Mybatisplus02DqlApplicationTests {
@Autowired private UserDao userDao; @Test void testGetAll(){ LambdaQueryWrapper<User> lqw = new LambdaQueryWrapper<User>(); lqw.lt(User::getAge, 10); List<User> userList = userDao.selectList(lqw); System.out.println(userList); }}
复制代码


这种方式就解决了上一种方式所存在的问题。

多条件构建

学完了三种构建查询对象的方式,每一种都有自己的特点,所以用哪一种都行,刚才都是一个条件,那如果有多个条件该如何构建呢?


需求:查询数据库表中,年龄在 10 岁到 30 岁之间的用户信息


@SpringBootTestclass Mybatisplus02DqlApplicationTests {
@Autowired private UserDao userDao; @Test void testGetAll(){ LambdaQueryWrapper<User> lqw = new LambdaQueryWrapper<User>(); lqw.lt(User::getAge, 30); lqw.gt(User::getAge, 10); List<User> userList = userDao.selectList(lqw); System.out.println(userList); }}
复制代码


  • gt:大于(>),最终的 SQL 语句为


  SELECT id,name,password,age,tel FROM user WHERE (age < ? AND age > ?)
复制代码


  • 构建多条件的时候,可以支持链式编程


  LambdaQueryWrapper<User> lqw = new LambdaQueryWrapper<User>();  lqw.lt(User::getAge, 30).gt(User::getAge, 10);  List<User> userList = userDao.selectList(lqw);  System.out.println(userList);
复制代码


需求:查询数据库表中,年龄小于 10 或年龄大于 30 的数据


@SpringBootTestclass Mybatisplus02DqlApplicationTests {
@Autowired private UserDao userDao; @Test void testGetAll(){ LambdaQueryWrapper<User> lqw = new LambdaQueryWrapper<User>(); lqw.lt(User::getAge, 10).or().gt(User::getAge, 30); List<User> userList = userDao.selectList(lqw); System.out.println(userList); }}
复制代码


  • or()就相当于我们 sql 语句中的or关键字,不加默认是and,最终的 sql 语句为:


  SELECT id,name,password,age,tel FROM user WHERE (age < ? OR age > ?)
复制代码

null 判定

先来看一张图,



  • 我们在做条件查询的时候,一般会有很多条件可以供用户进行选择查询。

  • 这些条件用户可以选择使用也可以选择不使用,比如我要查询价格在 8000 以上的手机

  • 在输入条件的时候,价格有一个区间范围,按照需求只需要在第一个价格输入框中输入 8000

  • 后台在做价格查询的时候,一般会让 price>值 1 and price <值 2

  • 因为前端没有输入值 2,所以如果不处理的话,就会出现 price>8000 and price < null 问题

  • 这个时候查询的结果就会出问题,具体该如何解决?



需求:查询数据库表中,根据输入年龄范围来查询符合条件的记录

用户在输入值的时候,

​ 如果只输入第一个框,说明要查询大于该年龄的用户

​ 如果只输入第二个框,说明要查询小于该年龄的用户

​ 如果两个框都输入了,说明要查询年龄在两个范围之间的用户


思考第一个问题:后台如果想接收前端的两个数据,该如何接收?


我们可以使用两个简单数据类型,也可以使用一个模型类,但是 User 类中目前只有一个 age 属性,如:


@Datapublic class User {    private Long id;    private String name;    private String password;    private Integer age;    private String tel;}
复制代码


使用一个 age 属性,如何去接收页面上的两个值呢?这个时候我们有两个解决方案


方案一:添加属性 age2,这种做法可以但是会影响到原模型类的属性内容


@Datapublic class User {    private Long id;    private String name;    private String password;    private Integer age;    private String tel;    private Integer age2;}
复制代码


方案二:新建一个模型类,让其继承 User 类,并在其中添加 age2 属性,UserQuery 在拥有 User 属性后同时添加了 age2 属性。


@Datapublic class User {    private Long id;    private String name;    private String password;    private Integer age;    private String tel;}
@Datapublic class UserQuery extends User { private Integer age2;}
复制代码


环境准备好后,我们来实现下刚才的需求:


@SpringBootTestclass Mybatisplus02DqlApplicationTests {
@Autowired private UserDao userDao; @Test void testGetAll(){ //模拟页面传递过来的查询数据 UserQuery uq = new UserQuery(); uq.setAge(10); uq.setAge2(30); LambdaQueryWrapper<User> lqw = new LambdaQueryWrapper<User>(); if(null != uq.getAge2()){ lqw.lt(User::getAge, uq.getAge2()); } if( null != uq.getAge()) { lqw.gt(User::getAge, uq.getAge()); } List<User> userList = userDao.selectList(lqw); System.out.println(userList); }}
复制代码


上面的写法可以完成条件为非空的判断,但是问题很明显,如果条件多的话,每个条件都需要判断,代码量就比较大,来看 MP 给我们提供的简化方式:


@SpringBootTestclass Mybatisplus02DqlApplicationTests {
@Autowired private UserDao userDao; @Test void testGetAll(){ //模拟页面传递过来的查询数据 UserQuery uq = new UserQuery(); uq.setAge(10); uq.setAge2(30); LambdaQueryWrapper<User> lqw = new LambdaQueryWrapper<User>(); lqw.lt(null!=uq.getAge2(),User::getAge, uq.getAge2()); lqw.gt(null!=uq.getAge(),User::getAge, uq.getAge()); List<User> userList = userDao.selectList(lqw); System.out.println(userList); }}
复制代码


d 当然这个也可以使用链式编程,如果太长了就要做些微的调整:


  • lt()方法


  • condition 为 boolean 类型,返回 true,则添加条件,返回 false 则不添加条件

发布于: 刚刚阅读数: 4
用户头像

fake smile by

关注

还未添加个人签名 2022.07.31 加入

还未添加个人简介

评论

发布
暂无评论
[MyBatisPlus]DQL编程控制①(条件查询)_Java_fake smile by_InfoQ写作社区