一、条件查询的类

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

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

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

二、环境构建

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

  • 创建一个SpringBoot项目

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

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

    1. <?xml version="1.0" encoding="UTF-8"?>
    2. <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    3.         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    4.    <modelVersion>4.0.0</modelVersion>
    5.    <parent>
    6.        <groupId>org.springframework.boot</groupId>
    7.        <artifactId>spring-boot-starter-parent</artifactId>
    8.        <version>2.5.0</version>
    9.    </parent>
    10.    <groupId>com.itheima</groupId>
    11.    <artifactId>mybatisplus_02_dql</artifactId>
    12.    <version>0.0.1-SNAPSHOT</version>
    13.    <properties>
    14.        <java.version>1.8</java.version>
    15.    </properties>
    16.    <dependencies>

    17.        <dependency>
    18.            <groupId>com.baomidou</groupId>
    19.            <artifactId>mybatis-plus-boot-starter</artifactId>
    20.            <version>3.4.1</version>
    21.        </dependency>

    22.        <dependency>
    23.            <groupId>org.springframework.boot</groupId>
    24.            <artifactId>spring-boot-starter</artifactId>
    25.        </dependency>

    26.        <dependency>
    27.            <groupId>com.alibaba</groupId>
    28.            <artifactId>druid</artifactId>
    29.            <version>1.1.16</version>
    30.        </dependency>

    31.        <dependency>
    32.            <groupId>mysql</groupId>
    33.            <artifactId>mysql-connector-java</artifactId>
    34.            <scope>runtime</scope>
    35.        </dependency>

    36.        <dependency>
    37.            <groupId>org.springframework.boot</groupId>
    38.            <artifactId>spring-boot-starter-test</artifactId>
    39.            <scope>test</scope>
    40.        </dependency>

    41.        <dependency>
    42.            <groupId>org.projectlombok</groupId>
    43.            <artifactId>lombok</artifactId>
    44.        </dependency>

    45.    </dependencies>

    46.    <build>
    47.        <plugins>
    48.            <plugin>
    49.                <groupId>org.springframework.boot</groupId>
    50.                <artifactId>spring-boot-maven-plugin</artifactId>
    51.            </plugin>
    52.        </plugins>
    53.    </build>

    54. </project>
  • 编写UserDao接口

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

    1. @Data
    2. public class User {
    3.    private Long id;
    4.    private String name;
    5.    private String password;
    6.    private Integer age;
    7.    private String tel;
    8. }
  • 编写引导类

    1. @SpringBootApplication
    2. public class Mybatisplus02DqlApplication {

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

    6. }
  • 编写配置文件

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

    1. @SpringBootTest
    2. class Mybatisplus02DqlApplicationTests {

    3.    @Autowired
    4.    private UserDao userDao;
    5.    
    6.    @Test
    7.    void testGetAll(){
    8.        List<User> userList = userDao.selectList(null);
    9.        System.out.println(userList);
    10.   }
    11. }

    最终创建的项目结构为:

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

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

      1. <?xml version="1.0" encoding="UTF-8"?>
      2. <configuration>
      3. </configuration>
    • 取消MybatisPlus启动banner图标

      application.yml添加如下内容:

      1. # mybatis-plus日志控制台输出
      2. mybatis-plus:
      3. configuration:
      4.   log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
      5. global-config:
      6.   banner: off # 关闭mybatisplus启动图标
    • 取消SpringBoot的log打印

      application.yml添加如下内容:

      1. spring:
      2. main:
      3.   banner-mode: off # 关闭SpringBoot启动图标(banner)

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

三、构建条件查询

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

  1. 先来看第一种:QueryWrapper

  1. @SpringBootTest
  2. class Mybatisplus02DqlApplicationTests {

  3.    @Autowired
  4.    private UserDao userDao;
  5.    
  6.    @Test
  7.    void testGetAll(){
  8.        QueryWrapper qw = new QueryWrapper();
  9.        qw.lt("age",18);
  10.        List<User> userList = userDao.selectList(qw);
  11.        System.out.println(userList);
  12.   }
  13. }
  • lt: 小于(<) ,最终的sql语句为

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

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

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

  1. @SpringBootTest
  2. class Mybatisplus02DqlApplicationTests {

  3.    @Autowired
  4.    private UserDao userDao;
  5.    
  6.    @Test
  7.    void testGetAll(){
  8.        QueryWrapper<User> qw = new QueryWrapper<User>();
  9.        qw.lambda().lt(User::getAge, 10);//添加条件
  10.        List<User> userList = userDao.selectList(qw);
  11.        System.out.println(userList);
  12.   }
  13. }
  • User::getAge,为lambda表达式中的,类名::方法名,最终的sql语句为:

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

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

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

  1. 接着来看第三种:LambdaQueryWrapper

  1. @SpringBootTest
  2. class Mybatisplus02DqlApplicationTests {

  3.    @Autowired
  4.    private UserDao userDao;
  5.    
  6.    @Test
  7.    void testGetAll(){
  8.        LambdaQueryWrapper<User> lqw = new LambdaQueryWrapper<User>();
  9.        lqw.lt(User::getAge, 10);
  10.        List<User> userList = userDao.selectList(lqw);
  11.        System.out.println(userList);
  12.   }
  13. }

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

四、多条件构建

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

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

  1. @SpringBootTest
  2. class Mybatisplus02DqlApplicationTests {

  3.    @Autowired
  4.    private UserDao userDao;
  5.    
  6.    @Test
  7.    void testGetAll(){
  8.        LambdaQueryWrapper<User> lqw = new LambdaQueryWrapper<User>();
  9.        lqw.lt(User::getAge, 30);
  10.        lqw.gt(User::getAge, 10);
  11.        List<User> userList = userDao.selectList(lqw);
  12.        System.out.println(userList);
  13.   }
  14. }
  • gt:大于(>),最终的SQL语句为

    1. SELECT id,name,password,age,tel FROM user WHERE (age < ? AND age > ?)
  • 构建多条件的时候,可以支持链式编程

    1. LambdaQueryWrapper<User> lqw = new LambdaQueryWrapper<User>();
    2. lqw.lt(User::getAge, 30).gt(User::getAge, 10);
    3. List<User> userList = userDao.selectList(lqw);
    4. System.out.println(userList);

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

  1. @SpringBootTest
  2. class Mybatisplus02DqlApplicationTests {

  3.    @Autowired
  4.    private UserDao userDao;
  5.    
  6.    @Test
  7.    void testGetAll(){
  8.        LambdaQueryWrapper<User> lqw = new LambdaQueryWrapper<User>();
  9.        lqw.lt(User::getAge, 10).or().gt(User::getAge, 30);
  10.        List<User> userList = userDao.selectList(lqw);
  11.        System.out.println(userList);
  12.   }
  13. }
  • or()就相当于我们sql语句中的or关键字,不加默认是and,最终的sql语句为:

    1. 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属性,如:

  1. @Data
  2. public class User {
  3.    private Long id;
  4.    private String name;
  5.    private String password;
  6.    private Integer age;
  7.    private String tel;
  8. }

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

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

  1. @Data
  2. public class User {
  3.    private Long id;
  4.    private String name;
  5.    private String password;
  6.    private Integer age;
  7.    private String tel;
  8.    private Integer age2;
  9. }

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

  1. @Data
  2. public class User {
  3.    private Long id;
  4.    private String name;
  5.    private String password;
  6.    private Integer age;
  7.    private String tel;
  8. }

  9. @Data
  10. public class UserQuery extends User {
  11.    private Integer age2;
  12. }

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

  1. @SpringBootTest
  2. class Mybatisplus02DqlApplicationTests {

  3.    @Autowired
  4.    private UserDao userDao;
  5.    
  6.    @Test
  7.    void testGetAll(){
  8.        //模拟页面传递过来的查询数据
  9.        UserQuery uq = new UserQuery();
  10.        uq.setAge(10);
  11.        uq.setAge2(30);
  12.        LambdaQueryWrapper<User> lqw = new LambdaQueryWrapper<User>();
  13.        if(null != uq.getAge2()){
  14.            lqw.lt(User::getAge, uq.getAge2());
  15.       }
  16.        if( null != uq.getAge()) {
  17.            lqw.gt(User::getAge, uq.getAge());
  18.       }
  19.        List<User> userList = userDao.selectList(lqw);
  20.        System.out.println(userList);
  21.   }
  22. }

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

  1. @SpringBootTest
  2. class Mybatisplus02DqlApplicationTests {

  3.    @Autowired
  4.    private UserDao userDao;
  5.    
  6.    @Test
  7.    void testGetAll(){
  8.        //模拟页面传递过来的查询数据
  9.        UserQuery uq = new UserQuery();
  10.        uq.setAge(10);
  11.        uq.setAge2(30);
  12.        LambdaQueryWrapper<User> lqw = new LambdaQueryWrapper<User>();
  13.        lqw.lt(null!=uq.getAge2(),User::getAge, uq.getAge2());
  14.        lqw.gt(null!=uq.getAge(),User::getAge, uq.getAge());
  15.        List<User> userList = userDao.selectList(lqw);
  16.        System.out.println(userList);
  17.   }
  18. }
  • 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. 【Android 逆向】switch 的smail特征

    JAVA 源码 ... String str1 = packedSwitch(1); ... private String packedSwitch(int i) { String str = nul ...

  2. day35-IO流02

    JavaOI流02 4.常用的类 4.1文件字节流输入流-FileInputStream InputStream抽象类是所有类字节输入流的超类 InputStream常用的子类: FileInputS ...

  3. Windows 10无法显示无线网络连接

    最近刚刚升级了一下操作系统,升级到了1903版本.正好又有一个HP的打印机安装了一下.结果,发现居然无法管理无线网络了.如果看不到图,请点我. 右击选择连接,也无法显示SSID. 驱动是从这个官网下载 ...

  4. Elasticsearch: 使用URI Search

    在Elasticsearch中,我们可以使用_search终端进行搜索.这个在我之前的文章 "开始使用Elasticsearch (2)" 中有很多的描述.针对这种搜索,我们可以使 ...

  5. C++ 自学笔记 new和delete(动态内存分配)

    动态内存分配 Dynamic memoey allocation C++使用new和delete 来申请和释放内存 new:先申请一个空间 int\Stash : 默认构造函数初始化对象 ~:析构函数 ...

  6. 深入理解AQS--jdk层面管程实现【管程详解的补充】

    什么是AQS 1.java.util.concurrent包中的大多数同步器实现都是围绕着共同的基础行为,比如等待队列.条件队列.独占获取.共享获取等,而这些行为的抽象就是基于AbstractQueu ...

  7. 浅谈-动态路由之OSPF的理解

    路由 在网络中,路由相当于就是一张地图,让路由器知道这个对应的IP数据包应该往哪端口.网段走:而这个"地图"我们称之为路由表,不同的目的IP路由表的下一个跳也不同,其生成方式有又有 ...

  8. vulnhub靶场之THE PLANETS: EARTH

    准备: 攻击机:虚拟机kali.本机win10. 靶机:THE PLANETS: EARTH,网段地址我这里设置的桥接,所以与本机电脑在同一网段,下载地址:https://download.vulnh ...

  9. Filter 筛选器(三)之 自定义一个启动事务的 TransactionScopeFilter

    如果一个方法内有多个写入操作,比如 写入A表,然后用A表的自增id 去写入B表,假如A表写入成功,但B表因为某种原因写入失败!(这就导致A表写入了脏数据) 这时候 我们可以自定义 一个Filter 进 ...

  10. 【编程学习】MATLAB

    目录 一.MATLAB基础 1. 学会完成MATLAB的安装与启动 1.1 软件包下载 1.2 安装步骤 2. 矩阵的基本操作与运算 2.1 矩阵的简单输入与操作 2.2 矩阵的基本运算 2.2.1 ...