4

Java开发学习(四十二)----MyBatisPlus查询语句之条件查询 - |旧市拾荒|

 1 year ago
source link: https://www.cnblogs.com/xiaoyh/p/16468183.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

Java开发学习(四十二)----MyBatisPlus查询语句之条件查询

一、条件查询的类

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

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

1126989-20220714203106681-114811690.png

那么条件查询如何使用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);
        }
    }

    最终创建的项目结构为:

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

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

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

      1126989-20220714203319772-384084475.png

      application.yml添加如下内容:

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

      1126989-20220714203335834-187025577.png

      application.yml添加如下内容:

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

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

三、构建条件查询

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

1126989-20220714203403631-544132171.png
  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判定

先来看一张图,

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

  • 这些条件用户可以选择使用也可以选择不使用,比如我要查询价格在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()方法

    1126989-20220714203626947-1381083614.png

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


如果您觉得阅读本文对您有帮助,请点一下“推荐”按钮,您的“推荐”将是我最大的写作动力!欢迎各位转载,但是未经作者本人同意,转载文章之后必须在文章页面明显位置给出作者和原文连接,否则保留追究法律责任的权利。

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK