一、条件查询的类
- 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> {
}</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);
  }
}</user>
* 测试的时候,控制台打印的日志比较多,速度有点慢而且不利于查看运行结果,所以接下来我们把这个日志处理下:
– 取消初始化spring日志打印,resources目录下添加logback.xml,名称固定,内容如下:
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
</configuration>
mybatis-plus日志控制台输出
mybatis-plus:
configuration:
  log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
global-config:
  banner: off # 关闭mybatisplus启动图标
spring:
main:
  banner-mode: off # 关闭SpringBoot启动图标(banner)
解决控制台打印日志过多的相关操作可以不用去做,一般会被用来方便我们查看程序运行的结果。
三、构建条件查询
在进行查询的时候,我们的入口是在Wrapper这个类上,因为它是一个接口,所以我们需要去找它对应的实现类,关于实现类也有很多,说明我们有多种构建查询条件对象的方式,
- 先来看第一种: 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);
  }
}</user>
- lt: 小于(
SELECT id,name,password,age,tel FROM user WHERE (age < ?)
第一种方式介绍完后,有个小问题就是在写条件的时候,容易出错,比如age写错,就会导致查询不成功
- 接着来看第二种: 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></user></user>
- User::getAge,为lambda表达式中的,类名::方法名,最终的sql语句为:
SELECT id,name,password,age,tel FROM user WHERE (age < ?)
注意:构建LambdaQueryWrapper的时候泛型不能省。
此时我们再次编写条件的时候,就不会存在写错名称的情况,但是qw后面多了一层lambda()调用
- 接着来看第三种: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);
  }
}</user></user></user>
这种方式就解决了上一种方式所存在的问题。
四、多条件构建
三种构建查询对象的方式,每一种都有自己的特点,所以用哪一种都行,刚才都是一个条件,那如果有多个条件该如何构建呢?
需求:查询数据库表中,年龄在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);
  }
}</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 {
​
   @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);
  }
}</user></user></user>
- 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,所以如果不处理的话,就会出现 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);
  }
}</user></user></user>
上面的写法可以完成条件为非空的判断,但是问题很明显,如果条件多的话,每个条件都需要判断,代码量就比较大,来看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);
  }
}</user></user></user>
- lt()方法 condition为boolean类型,返回true,则添加条件,返回false则不添加条件
Original: https://www.cnblogs.com/xiaoyh/p/16468183.html
Author: |旧市拾荒|
Title: Java开发学习(四十二)—-MyBatisPlus查询语句之条件查询
原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/798174/
转载文章受原作者版权保护。转载请注明原作者出处!