一、条件查询的类

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

这个我们在前面都有见过,比如查询所有和分页查询的时候,都有看到过一个Wrapper类,这个类就是用来构建查询条件的,如下图所示:

那么条件查询如何使用Wrapper来构建呢?

二、环境构建

在构建条件查询之前,我们先来准备下环境

  • 创建一个SpringBoot项目

    参考Java开发学习(三十五)----SpringBoot快速入门及起步依赖解析

  • pom.xml中添加对应的依赖

    <?xml version="1.0" encoding="UTF-8"?>
    <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
            xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
       <modelVersion>4.0.0</modelVersion>
       <parent>
           <groupId>org.springframework.boot</groupId>
           <artifactId>spring-boot-starter-parent</artifactId>
           <version>2.5.0</version>
       </parent>
       <groupId>com.itheima</groupId>
       <artifactId>mybatisplus_02_dql</artifactId>
       <version>0.0.1-SNAPSHOT</version>
       <properties>
           <java.version>1.8</java.version>
       </properties>
       <dependencies>

           <dependency>
               <groupId>com.baomidou</groupId>
               <artifactId>mybatis-plus-boot-starter</artifactId>
               <version>3.4.1</version>
           </dependency>

           <dependency>
               <groupId>org.springframework.boot</groupId>
               <artifactId>spring-boot-starter</artifactId>
           </dependency>

           <dependency>
               <groupId>com.alibaba</groupId>
               <artifactId>druid</artifactId>
               <version>1.1.16</version>
           </dependency>

           <dependency>
               <groupId>mysql</groupId>
               <artifactId>mysql-connector-java</artifactId>
               <scope>runtime</scope>
           </dependency>

           <dependency>
               <groupId>org.springframework.boot</groupId>
               <artifactId>spring-boot-starter-test</artifactId>
               <scope>test</scope>
           </dependency>

           <dependency>
               <groupId>org.projectlombok</groupId>
               <artifactId>lombok</artifactId>
           </dependency>

       </dependencies>

       <build>
           <plugins>
               <plugin>
                   <groupId>org.springframework.boot</groupId>
                   <artifactId>spring-boot-maven-plugin</artifactId>
               </plugin>
           </plugins>
       </build>

    </project>
  • 编写UserDao接口

    @Mapper
    public interface UserDao extends BaseMapper<User> {
    }
  • 编写模型类

    @Data
    public class User {
       private Long id;
       private String name;
       private String password;
       private Integer age;
       private String tel;
    }
  • 编写引导类

    @SpringBootApplication
    public class Mybatisplus02DqlApplication {

       public static void main(String[] args) {
           SpringApplication.run(Mybatisplus02DqlApplication.class, args);
      }

    }
  • 编写配置文件

    # dataSource
    spring:
    datasource:
      type: com.alibaba.druid.pool.DruidDataSource
      driver-class-name: com.mysql.cj.jdbc.Driver
      url: jdbc:mysql://localhost:3306/mybatisplus_db?serverTimezone=UTC
      username: root
      password: root
    # MybatisPlus日志
    mybatis-plus:
    configuration:
      log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
  • 编写测试类

    @SpringBootTest
    class Mybatisplus02DqlApplicationTests {

       @Autowired
       private UserDao userDao;
       
       @Test
       void testGetAll(){
           List<User> userList = userDao.selectList(null);
           System.out.println(userList);
      }
    }

    最终创建的项目结构为:

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

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

      <?xml version="1.0" encoding="UTF-8"?>
      <configuration>
      </configuration>
    • 取消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

@SpringBootTest
class 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

@SpringBootTest
class 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::getAge,为lambda表达式中的,类名::方法名,最终的sql语句为:

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

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

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

  1. 接着来看第三种:LambdaQueryWrapper

@SpringBootTest
class 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岁之间的用户信息

@SpringBootTest
class 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的数据

@SpringBootTest
class 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属性,如:

@Data
public class User {
   private Long id;
   private String name;
   private String password;
   private Integer age;
   private String tel;
}

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

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

@Data
public 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属性。

@Data
public class User {
   private Long id;
   private String name;
   private String password;
   private Integer age;
   private String tel;
}

@Data
public class UserQuery extends User {
   private Integer age2;
}

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

@SpringBootTest
class 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);
  }
}

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

@SpringBootTest
class 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);
  }
}
  • lt()方法

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

Java开发学习(四十二)----MyBatisPlus查询语句之条件查询的更多相关文章

  1. Java开发学习(四十)----MyBatisPlus入门案例与简介

    一.入门案例 MybatisPlus(简称MP)是基于MyBatis框架基础上开发的增强型工具,旨在简化开发.提供效率. SpringBoot它能快速构建Spring开发环境用以整合其他技术,使用起来 ...

  2. Java开发学习(三十二)----Maven多环境配置切换与跳过测试的三种方式

    一.多环境开发 我们平常都是在自己的开发环境进行开发, 当开发完成后,需要把开发的功能部署到测试环境供测试人员进行测试使用, 等测试人员测试通过后,我们会将项目部署到生成环境上线使用. 这个时候就有一 ...

  3. Java开发学习(四十一)----MyBatisPlus标准数据层(增删查改分页)开发

    一.标准CRUD使用 对于标准的CRUD功能都有哪些以及MyBatisPlus都提供了哪些方法可以使用呢? 我们先来看张图: 1.1 环境准备 这里用的环境就是Java开发学习(四十)----MyBa ...

  4. Java开发学习心得(二):Mybatis和Url路由

    目录 Java开发学习心得(二):Mybatis和Url路由 1.3 Mybatis 2 URL路由 2.1 @RequestMapping 2.2 @PathVariable 2.3 不同的请求类型 ...

  5. Java开发学习(三十六)----SpringBoot三种配置文件解析

    一. 配置文件格式 我们现在启动服务器默认的端口号是 8080,访问路径可以书写为 http://localhost:8080/books/1 在线上环境我们还是希望将端口号改为 80,这样在访问的时 ...

  6. 网站开发进阶(四十二)巧用clear:both

    网站开发进阶(四十二)巧用clear:both 前言 我们在制作网页中用div+css或者称xhtml+css都会遇到一些很诡异的情况,明明布局正确,但是整个画面却混乱起来了,有时候在IE6下看的很正 ...

  7. java jvm学习笔记十二(访问控制器的栈校验机制)

    欢迎装载请说明出处:http://blog.csdn.net/yfqnihao 本节源码:http://download.csdn.net/detail/yfqnihao/4863854 这一节,我们 ...

  8. Java开发学习(三十四)----Maven私服(二)本地仓库访问私服配置与私服资源上传下载

    一.本地仓库访问私服配置 我们通过IDEA将开发的模块上传到私服,中间是要经过本地Maven的 本地Maven需要知道私服的访问地址以及私服访问的用户名和密码 私服中的仓库很多,Maven最终要把资源 ...

  9. java web学习总结(十二) -------------------Session

    一.Session简单介绍 在WEB开发中,服务器可以为每个用户浏览器创建一个会话对象(session对象),注意:一个浏览器独占一个session对象(默认情况下).因此,在需要保存用户数据时,服务 ...

  10. 阿里巴巴 Java 开发手册 (十二)安全规约

    1. [强制]隶属于用户个人的页面或者功能必须进行权限控制校验. 说明:防止没有做水平权限校验就可随意访问.修改.删除别人的数据,比如查看他人的私信 内容.修改他人的订单. 2. [强制]用户敏感数据 ...

随机推荐

  1. day38-IO流05

    JavaIO流05 4.常用的类04 4.4节点流和处理流03 4.4.8打印流-PrintStream和PrintWriter 打印流只有输出流,没有输入流 1.简单介绍及应用 PrintStrea ...

  2. 全网最全Redis学习

    一.Redis简介 Redis是以Key-Value形式进行存储的NoSQL数据库,C语言进行编写的.平时操作的数据都在内存中,效率特高,读的效率110000/s,写81000/s,所以多把Redis ...

  3. C++程序的内存分布

    4.文字常量区: p与p1的指针地址一致,且字符串常量是不能被改变的. 5.程序代码区:存放一系列代码. 动态内存 1.按需分配,根据需要分配内存,不浪费. 内存拷贝函数 void *memcpy(v ...

  4. Git将本地仓库上传到github

    这里采用简单的描述,提供两种方式: 一.连接本地文件夹和远程仓库 1.使用pull--拉取github项目文件 (1)进入到自己要上传的文件夹内部,然后git bash here (2)输入命令 gi ...

  5. 第四周(实际是n+周)

    1. tomcat启动报错 报错内容:ERROR RUNNING 'TOMCAT': UNABLE TO OPEN DEBUGGER PORT (127.0.0.1:38667): JAVA.NET. ...

  6. 安装krew

    地址:https://krew.sigs.k8s.io/docs/user-guide/setup/install/ macOS/Linux Bash or ZSH shells 确保已安装git 2 ...

  7. 组件化开发1-git命令简洁版

    1-给项目添加git git init 2-查询当前状态,(红色显示的为在工作区,绿色为暂缓区) git status 3-提交到暂缓区 git add . 4-提交到本地仓库('xxxx'里面为注释 ...

  8. echarts BAR堆叠图显示百分比

    在使用echarts的堆叠图时,我们鼠标悬停的浮窗里的信息可能并不是我们想要的信息,这个时候需要我们配置一下,因为堆叠图的trigger的类型是坐标轴触发的,数据是多组数据,所以我们需要遍历一下数据, ...

  9. PAT (Basic Level) Practice 1008 数组元素循环右移问题 分数 20

    一个数组A中存有N(>0)个整数,在不允许使用另外数组的前提下,将每个整数循环向右移M(≥0)个位置,即将A中的数据由(A0​A1​⋯AN−1​)变换为(AN−M​⋯AN−1​A0​A1​⋯AN ...

  10. 一文读懂Apache Geode缓存中间件

    目录 一.对缓存中间件的诉求 1.1 我们为什么需要缓存中间件 1.2 缓存的分类 1.1.1 弱势缓存 1.1.2 强势缓存 二.什么是Apache Geode 2.1 Apache Geode的架 ...