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

一、条件查询的类

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

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

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

那么条件查询如何使用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">
 &#xA0; &#xA0;<modelversion>4.0.0</modelversion>
 &#xA0; &#xA0;<parent>
 &#xA0; &#xA0; &#xA0; &#xA0;<groupid>org.springframework.boot</groupid>
 &#xA0; &#xA0; &#xA0; &#xA0;<artifactid>spring-boot-starter-parent</artifactid>
 &#xA0; &#xA0; &#xA0; &#xA0;<version>2.5.0</version>
 &#xA0; &#xA0;</parent>
 &#xA0; &#xA0;<groupid>com.itheima</groupid>
 &#xA0; &#xA0;<artifactid>mybatisplus_02_dql</artifactid>
 &#xA0; &#xA0;<version>0.0.1-SNAPSHOT</version>
 &#xA0; &#xA0;<properties>
 &#xA0; &#xA0; &#xA0; &#xA0;<java.version>1.8</java.version>
 &#xA0; &#xA0;</properties>
 &#xA0; &#xA0;<dependencies>
&#x200B;
 &#xA0; &#xA0; &#xA0; &#xA0;<dependency>
 &#xA0; &#xA0; &#xA0; &#xA0; &#xA0; &#xA0;<groupid>com.baomidou</groupid>
 &#xA0; &#xA0; &#xA0; &#xA0; &#xA0; &#xA0;<artifactid>mybatis-plus-boot-starter</artifactid>
 &#xA0; &#xA0; &#xA0; &#xA0; &#xA0; &#xA0;<version>3.4.1</version>
 &#xA0; &#xA0; &#xA0; &#xA0;</dependency>
&#x200B;
 &#xA0; &#xA0; &#xA0; &#xA0;<dependency>
 &#xA0; &#xA0; &#xA0; &#xA0; &#xA0; &#xA0;<groupid>org.springframework.boot</groupid>
 &#xA0; &#xA0; &#xA0; &#xA0; &#xA0; &#xA0;<artifactid>spring-boot-starter</artifactid>
 &#xA0; &#xA0; &#xA0; &#xA0;</dependency>
&#x200B;
 &#xA0; &#xA0; &#xA0; &#xA0;<dependency>
 &#xA0; &#xA0; &#xA0; &#xA0; &#xA0; &#xA0;<groupid>com.alibaba</groupid>
 &#xA0; &#xA0; &#xA0; &#xA0; &#xA0; &#xA0;<artifactid>druid</artifactid>
 &#xA0; &#xA0; &#xA0; &#xA0; &#xA0; &#xA0;<version>1.1.16</version>
 &#xA0; &#xA0; &#xA0; &#xA0;</dependency>
&#x200B;
 &#xA0; &#xA0; &#xA0; &#xA0;<dependency>
 &#xA0; &#xA0; &#xA0; &#xA0; &#xA0; &#xA0;<groupid>mysql</groupid>
 &#xA0; &#xA0; &#xA0; &#xA0; &#xA0; &#xA0;<artifactid>mysql-connector-java</artifactid>
 &#xA0; &#xA0; &#xA0; &#xA0; &#xA0; &#xA0;<scope>runtime</scope>
 &#xA0; &#xA0; &#xA0; &#xA0;</dependency>
&#x200B;
 &#xA0; &#xA0; &#xA0; &#xA0;<dependency>
 &#xA0; &#xA0; &#xA0; &#xA0; &#xA0; &#xA0;<groupid>org.springframework.boot</groupid>
 &#xA0; &#xA0; &#xA0; &#xA0; &#xA0; &#xA0;<artifactid>spring-boot-starter-test</artifactid>
 &#xA0; &#xA0; &#xA0; &#xA0; &#xA0; &#xA0;<scope>test</scope>
 &#xA0; &#xA0; &#xA0; &#xA0;</dependency>
&#x200B;
 &#xA0; &#xA0; &#xA0; &#xA0;<dependency>
 &#xA0; &#xA0; &#xA0; &#xA0; &#xA0; &#xA0;<groupid>org.projectlombok</groupid>
 &#xA0; &#xA0; &#xA0; &#xA0; &#xA0; &#xA0;<artifactid>lombok</artifactid>
 &#xA0; &#xA0; &#xA0; &#xA0;</dependency>
&#x200B;
 &#xA0; &#xA0;</dependencies>
&#x200B;
 &#xA0; &#xA0;<build>
 &#xA0; &#xA0; &#xA0; &#xA0;<plugins>
 &#xA0; &#xA0; &#xA0; &#xA0; &#xA0; &#xA0;<plugin>
 &#xA0; &#xA0; &#xA0; &#xA0; &#xA0; &#xA0; &#xA0; &#xA0;<groupid>org.springframework.boot</groupid>
 &#xA0; &#xA0; &#xA0; &#xA0; &#xA0; &#xA0; &#xA0; &#xA0;<artifactid>spring-boot-maven-plugin</artifactid>
 &#xA0; &#xA0; &#xA0; &#xA0; &#xA0; &#xA0;</plugin>
 &#xA0; &#xA0; &#xA0; &#xA0;</plugins>
 &#xA0; &#xA0;</build>
&#x200B;
</project>
&#x200B;
  • 编写UserDao接口
@Mapper
public interface UserDao extends BaseMapper<user> {
}</user>
  • 编写模型类
@Data
public class User {
 &#xA0; &#xA0;private Long id;
 &#xA0; &#xA0;private String name;
 &#xA0; &#xA0;private String password;
 &#xA0; &#xA0;private Integer age;
 &#xA0; &#xA0;private String tel;
}
  • 编写引导类
@SpringBootApplication
public class Mybatisplus02DqlApplication {
&#x200B;
 &#xA0; &#xA0;public static void main(String[] args) {
 &#xA0; &#xA0; &#xA0; &#xA0;SpringApplication.run(Mybatisplus02DqlApplication.class, args);
 &#xA0;  }
&#x200B;
}
  • 编写配置文件
dataSource
spring:
  datasource:
 &#xA0;  type: com.alibaba.druid.pool.DruidDataSource
 &#xA0;  driver-class-name: com.mysql.cj.jdbc.Driver
 &#xA0;  url: jdbc:mysql://localhost:3306/mybatisplus_db?serverTimezone=UTC
 &#xA0;  username: root
 &#xA0;  password: root
MybatisPlus&#x65E5;&#x5FD7;
mybatis-plus:
  configuration:
 &#xA0;  log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
  • 编写测试类
@SpringBootTest
class Mybatisplus02DqlApplicationTests {
&#x200B;
 &#xA0; &#xA0;@Autowired
 &#xA0; &#xA0;private UserDao userDao;
 &#xA0; &#xA0;
 &#xA0; &#xA0;@Test
 &#xA0; &#xA0;void testGetAll(){
 &#xA0; &#xA0; &#xA0; &#xA0;List<user> userList = userDao.selectList(null);
 &#xA0; &#xA0; &#xA0; &#xA0;System.out.println(userList);
 &#xA0;  }
}</user>

Java开发学习(四十二)----MyBatisPlus查询语句之条件查询
* 测试的时候,控制台打印的日志比较多,速度有点慢而且不利于查看运行结果,所以接下来我们把这个日志处理下:
– 取消初始化spring日志打印,resources目录下添加logback.xml,名称固定,内容如下:
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
</configuration>

Java开发学习(四十二)----MyBatisPlus查询语句之条件查询
mybatis-plus&#x65E5;&#x5FD7;&#x63A7;&#x5236;&#x53F0;&#x8F93;&#x51FA;
mybatis-plus:
  configuration:
 &#xA0;  log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
  global-config:
 &#xA0;  banner: off # &#x5173;&#x95ED;mybatisplus&#x542F;&#x52A8;&#x56FE;&#x6807;

Java开发学习(四十二)----MyBatisPlus查询语句之条件查询
spring:
  main:
 &#xA0;  banner-mode: off # &#x5173;&#x95ED;SpringBoot&#x542F;&#x52A8;&#x56FE;&#x6807;(banner)

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

三、构建条件查询

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

Java开发学习(四十二)----MyBatisPlus查询语句之条件查询
  1. 先来看第一种: QueryWrapper
@SpringBootTest
class Mybatisplus02DqlApplicationTests {
&#x200B;
 &#xA0; &#xA0;@Autowired
 &#xA0; &#xA0;private UserDao userDao;
 &#xA0; &#xA0;
 &#xA0; &#xA0;@Test
 &#xA0; &#xA0;void testGetAll(){
 &#xA0; &#xA0; &#xA0; &#xA0;QueryWrapper qw = new QueryWrapper();
 &#xA0; &#xA0; &#xA0; &#xA0;qw.lt("age",18);
 &#xA0; &#xA0; &#xA0; &#xA0;List<user> userList = userDao.selectList(qw);
 &#xA0; &#xA0; &#xA0; &#xA0;System.out.println(userList);
 &#xA0;  }
}</user>
  • lt: 小于(
SELECT id,name,password,age,tel FROM user WHERE (age < ?)

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

  1. 接着来看第二种: QueryWrapper的基础上使用lambda
@SpringBootTest
class Mybatisplus02DqlApplicationTests {
&#x200B;
 &#xA0; &#xA0;@Autowired
 &#xA0; &#xA0;private UserDao userDao;
 &#xA0; &#xA0;
 &#xA0; &#xA0;@Test
 &#xA0; &#xA0;void testGetAll(){
 &#xA0; &#xA0; &#xA0; &#xA0;QueryWrapper<user> qw = new QueryWrapper<user>();
 &#xA0; &#xA0; &#xA0; &#xA0;qw.lambda().lt(User::getAge, 10);//&#x6DFB;&#x52A0;&#x6761;&#x4EF6;
 &#xA0; &#xA0; &#xA0; &#xA0;List<user> userList = userDao.selectList(qw);
 &#xA0; &#xA0; &#xA0; &#xA0;System.out.println(userList);
 &#xA0;  }
}</user></user></user>
  • User::getAge,为lambda表达式中的,类名::方法名,最终的sql语句为:
SELECT id,name,password,age,tel FROM user WHERE (age < ?)

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

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

  1. 接着来看第三种:LambdaQueryWrapper
@SpringBootTest
class Mybatisplus02DqlApplicationTests {
&#x200B;
 &#xA0; &#xA0;@Autowired
 &#xA0; &#xA0;private UserDao userDao;
 &#xA0; &#xA0;
 &#xA0; &#xA0;@Test
 &#xA0; &#xA0;void testGetAll(){
 &#xA0; &#xA0; &#xA0; &#xA0;LambdaQueryWrapper<user> lqw = new LambdaQueryWrapper<user>();
 &#xA0; &#xA0; &#xA0; &#xA0;lqw.lt(User::getAge, 10);
 &#xA0; &#xA0; &#xA0; &#xA0;List<user> userList = userDao.selectList(lqw);
 &#xA0; &#xA0; &#xA0; &#xA0;System.out.println(userList);
 &#xA0;  }
}</user></user></user>

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

四、多条件构建

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

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

@SpringBootTest
class Mybatisplus02DqlApplicationTests {
&#x200B;
 &#xA0; &#xA0;@Autowired
 &#xA0; &#xA0;private UserDao userDao;
 &#xA0; &#xA0;
 &#xA0; &#xA0;@Test
 &#xA0; &#xA0;void testGetAll(){
 &#xA0; &#xA0; &#xA0; &#xA0;LambdaQueryWrapper<user> lqw = new LambdaQueryWrapper<user>();
 &#xA0; &#xA0; &#xA0; &#xA0;lqw.lt(User::getAge, 30);
 &#xA0; &#xA0; &#xA0; &#xA0;lqw.gt(User::getAge, 10);
 &#xA0; &#xA0; &#xA0; &#xA0;List<user> userList = userDao.selectList(lqw);
 &#xA0; &#xA0; &#xA0; &#xA0;System.out.println(userList);
 &#xA0;  }
}</user></user></user>
  • 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);</user></user></user>

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

@SpringBootTest
class Mybatisplus02DqlApplicationTests {
&#x200B;
 &#xA0; &#xA0;@Autowired
 &#xA0; &#xA0;private UserDao userDao;
 &#xA0; &#xA0;
 &#xA0; &#xA0;@Test
 &#xA0; &#xA0;void testGetAll(){
 &#xA0; &#xA0; &#xA0; &#xA0;LambdaQueryWrapper<user> lqw = new LambdaQueryWrapper<user>();
 &#xA0; &#xA0; &#xA0; &#xA0;lqw.lt(User::getAge, 10).or().gt(User::getAge, 30);
 &#xA0; &#xA0; &#xA0; &#xA0;List<user> userList = userDao.selectList(lqw);
 &#xA0; &#xA0; &#xA0; &#xA0;System.out.println(userList);
 &#xA0;  }
}</user></user></user>
  • or()就相当于我们sql语句中的 or关键字,不加默认是 and,最终的sql语句为:
SELECT id,name,password,age,tel FROM user WHERE (age < ? OR age > ?)

五、null判定

先来看一张图,

Java开发学习(四十二)----MyBatisPlus查询语句之条件查询
  • 我们在做条件查询的时候,一般会有很多条件可以供用户进行选择查询。
  • 这些条件用户可以选择使用也可以选择不使用,比如我要查询价格在8000以上的手机
  • 在输入条件的时候,价格有一个区间范围,按照需求只需要在第一个价格输入框中输入8000
  • 后台在做价格查询的时候,一般会让 price>值1 and price
  • 因为前端没有输入值2,所以如果不处理的话,就会出现 price>8000 and price < null问题
  • 这个时候查询的结果就会出问题,具体该如何解决?

需求:查询数据库表中,根据输入年龄范围来查询符合条件的记录
用户在输入值的时候,
如果只输入第一个框,说明要查询大于该年龄的用户
如果只输入第二个框,说明要查询小于该年龄的用户
如果两个框都输入了,说明要查询年龄在两个范围之间的用户

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

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

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

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

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

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

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

@Data
public class User {
 &#xA0; &#xA0;private Long id;
 &#xA0; &#xA0;private String name;
 &#xA0; &#xA0;private String password;
 &#xA0; &#xA0;private Integer age;
 &#xA0; &#xA0;private String tel;
}
&#x200B;
@Data
public class UserQuery extends User {
 &#xA0; &#xA0;private Integer age2;
}

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

@SpringBootTest
class Mybatisplus02DqlApplicationTests {
&#x200B;
 &#xA0; &#xA0;@Autowired
 &#xA0; &#xA0;private UserDao userDao;
 &#xA0; &#xA0;
 &#xA0; &#xA0;@Test
 &#xA0; &#xA0;void testGetAll(){
 &#xA0; &#xA0; &#xA0; &#xA0;//&#x6A21;&#x62DF;&#x9875;&#x9762;&#x4F20;&#x9012;&#x8FC7;&#x6765;&#x7684;&#x67E5;&#x8BE2;&#x6570;&#x636E;
 &#xA0; &#xA0; &#xA0; &#xA0;UserQuery uq = new UserQuery();
 &#xA0; &#xA0; &#xA0; &#xA0;uq.setAge(10);
 &#xA0; &#xA0; &#xA0; &#xA0;uq.setAge2(30);
 &#xA0; &#xA0; &#xA0; &#xA0;LambdaQueryWrapper<user> lqw = new LambdaQueryWrapper<user>();
 &#xA0; &#xA0; &#xA0; &#xA0;if(null != uq.getAge2()){
 &#xA0; &#xA0; &#xA0; &#xA0; &#xA0; &#xA0;lqw.lt(User::getAge, uq.getAge2());
 &#xA0; &#xA0; &#xA0;  }
 &#xA0; &#xA0; &#xA0; &#xA0;if( null != uq.getAge()) {
 &#xA0; &#xA0; &#xA0; &#xA0; &#xA0; &#xA0;lqw.gt(User::getAge, uq.getAge());
 &#xA0; &#xA0; &#xA0;  }
 &#xA0; &#xA0; &#xA0; &#xA0;List<user> userList = userDao.selectList(lqw);
 &#xA0; &#xA0; &#xA0; &#xA0;System.out.println(userList);
 &#xA0;  }
}</user></user></user>

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

@SpringBootTest
class Mybatisplus02DqlApplicationTests {
&#x200B;
 &#xA0; &#xA0;@Autowired
 &#xA0; &#xA0;private UserDao userDao;
 &#xA0; &#xA0;
 &#xA0; &#xA0;@Test
 &#xA0; &#xA0;void testGetAll(){
 &#xA0; &#xA0; &#xA0; &#xA0;//&#x6A21;&#x62DF;&#x9875;&#x9762;&#x4F20;&#x9012;&#x8FC7;&#x6765;&#x7684;&#x67E5;&#x8BE2;&#x6570;&#x636E;
 &#xA0; &#xA0; &#xA0; &#xA0;UserQuery uq = new UserQuery();
 &#xA0; &#xA0; &#xA0; &#xA0;uq.setAge(10);
 &#xA0; &#xA0; &#xA0; &#xA0;uq.setAge2(30);
 &#xA0; &#xA0; &#xA0; &#xA0;LambdaQueryWrapper<user> lqw = new LambdaQueryWrapper<user>();
 &#xA0; &#xA0; &#xA0; &#xA0;lqw.lt(null!=uq.getAge2(),User::getAge, uq.getAge2());
 &#xA0; &#xA0; &#xA0; &#xA0;lqw.gt(null!=uq.getAge(),User::getAge, uq.getAge());
 &#xA0; &#xA0; &#xA0; &#xA0;List<user> userList = userDao.selectList(lqw);
 &#xA0; &#xA0; &#xA0; &#xA0;System.out.println(userList);
 &#xA0;  }
}</user></user></user>
  • lt()方法 Java开发学习(四十二)----MyBatisPlus查询语句之条件查询 condition为boolean类型,返回true,则添加条件,返回false则不添加条件

Original: https://www.cnblogs.com/xiaoyh/p/16468183.html
Author: |旧市拾荒|
Title: Java开发学习(四十二)—-MyBatisPlus查询语句之条件查询

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/798174/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球