当前位置: 首页 > news >正文

[Mybatis-Plus笔记] MybatisPlus-03-QueryWrapper条件构造器

[Mybatis-Plus笔记] MybatisPlus-03-QueryWrapper条件构造器入门

  • 一、准备工作
  • 二、条件构造器入门
    • 1. 使用方式
      • (1)普通 QueryWrapper
      • (2)lambda 方式 QueryWrapper
      • (3)LambdaQueryWrapper
    • 2. 条件的逻辑连接
      • (1)与运算
      • (2)或运算
      • (3)括号
    • 3. 更多条件判断方法
  • 三、补充
    • 1. 增加布尔值参数
    • 2. 查询映射
    • 3. selectMaps() 方法

一、准备工作

为了更好的理解条件构造器,建议配置 Mybatis-Plus 的日志输出到控制台

在 yaml 配置文件中加入下面内容:

mybatis-plus:
  configuration:
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl

如此配置后,我们可以在控制台看到 Mybatis-Plus 生成的 SQL 语句

二、条件构造器入门

1. 使用方式

(1)普通 QueryWrapper

下面的测试类中,实现了从表中查询 age 字段小于 20 的用户

然后利用 selectList 方法,将条件构造器作为参数传入,即可得到符合条件的数据

@SpringBootTest
public class MybatisPlusTest {
    @Autowired
    UserMapper userMapper;
    @Test
    void testQueryWrapper() {
        QueryWrapper condition = new QueryWrapper();
        // 方法名 lt 表示小于,参数是字段名与值
        condition.lt("age", 20);
        List<User> users = userMapper.selectList(condition);
        System.out.println(users);
    }

}

[注意]

  • 不指定 QueryWrapper 的泛型无法进行链式编程

SQL 语句为:

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

(2)lambda 方式 QueryWrapper

通过指定实体类的 get 方法来确定列,避免了写错类名带来的麻烦

需要指定泛型为实体类,并以 lambda() 方法开头

可以链式编程

@SpringBootTest
public class MybatisPlusTest {
    @Autowired
    UserMapper userMapper;
    @Test
    void testQueryWrapper() {
        QueryWrapper<User> condition = new QueryWrapper<User>();
//        condition.lt("age", 20);
        condition.lambda().lt(User::getAge, 20);
        List<User> users = userMapper.selectList(condition);
        System.out.println(users);
    }

}

SQL 语句也是:

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

(3)LambdaQueryWrapper

使用 LambdaQueryWrapper 就不用指定再写 lambda() 方法开头了

但不可再通过列名来指定字段

@SpringBootTest
public class MybatisPlusTest {
    @Autowired
    UserMapper userMapper;
    @Test
    void testQueryWrapper() {
        LambdaQueryWrapper<User> condition = new LambdaQueryWrapper<User>();
//        condition.lt("age", 20);  // 不可用
        condition.lt(User::getAge, 20);
        List<User> users = userMapper.selectList(condition);
        System.out.println(users);
    }

}

SQL 语句依然是:

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

2. 条件的逻辑连接

(1)与运算

对同一个条件构造器添加多个条件,默认用与运算(或者说且运算)连接

如下例完成 20 <= age <= 30 的条件构造(ge 和 le 分别表示 >= 和 <=)

@SpringBootTest
public class MybatisPlusTest {
    @Autowired
    UserMapper userMapper;
    @Test
    void testQueryWrapper() {
        QueryWrapper<User> condition = new QueryWrapper<User>();
        condition.lambda()
                .ge(User::getAge, 20).le(User::getAge, 30);
        List<User> users = userMapper.selectList(condition);
        System.out.println(users);
    }

}

SQL 语句为:

SELECT id,name,age,email FROM user WHERE (age >= ? AND age <= ?)

(2)或运算

多个条件间用 or() 方法分隔,条件就会用或运算连接

如下例完成 age < 20 || age > 30 的条件构造(lt 和 gt 分别表示 < 和 >)

@SpringBootTest
public class MybatisPlusTest {
    @Autowired
    UserMapper userMapper;
    @Test
    void testQueryWrapper() {
        QueryWrapper<User> condition = new QueryWrapper<User>();
        condition.lambda().
                lt(User::getAge, 20).or().gt(User::getAge, 30);
        List<User> users = userMapper.selectList(condition);
        System.out.println(users);
    }

}

SQL 语句为:

SELECT id,name,age,email FROM user WHERE (age < ? OR age > ?)

(3)括号

条件构造器中,and() 方法表示括号(或者说嵌套),而不是且运算

我们需要将括号中的内容作为参数传入 and() 方法

例如,我们需要在年龄低于 20 或者高于 35 的用户中,找出使用 @gmail 邮箱的用户

可以像下面这样:

@SpringBootTest
public class MybatisPlusTest {
    @Autowired
    UserMapper userMapper;
    @Test
    void testQueryWrapper() {
        QueryWrapper<User> condition = new QueryWrapper<User>();
        condition.lambda()
                .and(
                        i -> i.lt(User::getAge, 20).or().gt(User::getAge, 35)
                ).likeLeft(User::getEmail, "@gmail.com");
        List<User> users = userMapper.selectList(condition);
        System.out.println(users);
    }

}

关于 and() 方法中的 lambda 表达式,在 idea 中 按住 ctrl 将鼠标放在 i 上,可以看到,i 指代的是一个 LambdaQueryWrapper<User>

在这里插入图片描述

SQL 语句为:

SELECT id,name,age,email FROM user WHERE ((age < ? OR age > ?) AND email LIKE ?)

参数为 :

Parameters: 20(Integer), 35(Integer), %@gmail.com(String)

可见 likeLeft() 方法自动给参数左侧加上了 % 通配符
类似的还有 likeRight() 在右侧加 %
like() 在左右侧都加 %

3. 更多条件判断方法

lt, le, gt, ge 这些代表条件判断的代码,最早还是在 Shell 脚本中见到的

想要了解更多的话推荐这一篇文章:Mybatis Plus详解(三)——条件构造器详解

三、补充

1. 增加布尔值参数

在条件构造器添加条件是,可以再加入一个 boolean 值表示是否要将此条件加入。

看下例中,服务层实现了根据年龄区间查询用户的功能:

@Service
public class UserServiceImpl implements UserService {
    @Autowired
    UserMapper userMapper;

    @Override
    public List<User> selectByAgeRange(Integer low, Integer high) {
        QueryWrapper<User> condition = new QueryWrapper<>();
        condition.lambda()
                .ge(User::getAge, low)
                .lt(User::getAge, high);
        return userMapper.selectList(condition);
    }
}

但是参数为 null 时会怎样呢?测试一下看看:

@SpringBootTest
public class UserServiceTest {
    @Autowired
    UserService userService;
    @Test
    void testSelectByAgeRange() {
        List<User> users = userService.selectByAgeRange(null, 20);
        System.out.println(users);
    }
}

用 null 和 20 做参数,一般希望能忽略下限,查询小于 20 岁的用户,但实际上没有查到任何结果

Mybatis-Plus 日志如下:

==>  Preparing: SELECT id,name,age,email FROM user WHERE (age >= ? AND age < ?)
==> Parameters: null, 20(Integer)
<==      Total: 0

如果某个参数为空,则不将此条件加入构造,可以这样写:

@Service
public class UserServiceImpl implements UserService {
    @Autowired
    UserMapper userMapper;

    @Override
    public List<User> selectByAgeRange(Integer low, Integer high) {
        QueryWrapper<User> condition = new QueryWrapper<>();
        condition.lambda()
                .ge(low != null, User::getAge, low)
                .lt(high != null, User::getAge, high);
        return userMapper.selectList(condition);
    }
}

ge 和 lt 方法中多了一个布尔值参数,当这个参数为真时才会加入此条件

再次执行测试,日志如下:

==>  Preparing: SELECT id,name,age,email FROM user WHERE (age < ?)
==> Parameters: 20(Integer)
<==    Columns: id, name, age, email
<==        Row: 2, Tao Chi Yuen, 17, chiyuentao@icloud.com
<==        Row: 4, Ueno Hikari, 18, hikari9@hotmail.com
<==        Row: 12, Mildred Ramirez, 19, ramirez2@icloud.com
<==      Total: 3

2. 查询映射

select() 方法可以指定查询的内容,参数为字符串可变参数,将表的字段名做为参数传入

默认查询所有字段,如果没有参数传入则无效

Mybatis-Plus 会在多个参数间添加逗号,然后放在 SQL 语句的 SELECT 之后

我们直接用 SQL 语句作为参数传入也可以

select() 方法的效果不会叠加,多次调用 select() 方法时以最后一次为准,最后一次无参数不会覆盖之前的

示例:

@SpringBootTest
public class MybatisPlusTest {
    @Autowired
    UserMapper userMapper;
    @Test
    void testSelect() {
        QueryWrapper<User> wrapper = new QueryWrapper<>();
        wrapper.select("age");
        wrapper.select("name, email");
        wrapper.select("name AS userName, email AS userEmail");
        wrapper.select();
        userMapper.selectList(wrapper);
    }
}

Mybatis-Plus 日志如下:

==>  Preparing: SELECT name AS userName, email AS userEmail FROM user
==> Parameters: 
<==    Columns: userName, userEmail
<==        Row: Pauline Cole, paulic59@icloud.com
<==        Row: Tao Chi Yuen, chiyuentao@icloud.com
<==      Total: 2

3. selectMaps() 方法

如果查询到的数据是不能装进实体类中的,就要调用 selectMaps() 方法了,用 List<Map<String, Object>> 接收结果

比如聚合函数查询平均年龄,如下:

@SpringBootTest
public class MybatisPlusTest {
    @Autowired
    UserMapper userMapper;
    @Test
    void testSelectMaps() {
        QueryWrapper<User> wrapper = new QueryWrapper<>();
        wrapper.select("AVG(age) AS averageAge");
        List<Map<String, Object>> maps = userMapper.selectMaps(wrapper);
        
        System.out.println(maps);
        BigDecimal averageAge = (BigDecimal) maps.get(0).get("averageAge");
        System.out.println("averageAge = " + averageAge);
    }
}

另外,AVG() 聚合函数得到的结果是 BigDecimal 类型,而不是 double

Mybatis-Plus 日志如下:

==>  Preparing: SELECT AVG(age) AS averageAge FROM user
==> Parameters: 
<==    Columns: averageAge
<==        Row: 21.8438
<==      Total: 1

相关文章:

  • STM32F1定时器-PWM输出
  • CNN天气识别
  • 基于SpringBoot+Vue的校园招聘管理系统(Java毕业设计)
  • java File类基本概念基本构造方法使用
  • 基于Java微服务方案的商品秒杀系统
  • 谷粒商城 高级篇(一) --------- ElasticSearch 的简介与安装
  • mybatis的sql标签
  • 面试题-参加生日宴会的最多人数
  • 开发运维-常用远程桌面开源软件
  • 【JAVA】SrpingMVC(上)—— 注解请求与响应
  • ZZCMS201910代码审计
  • HTTPDNS
  • ApacheDBUtils的使用
  • 补涨行情的模式如何做?(几天几板模式)
  • 基于Levy飞行策略的改进樽海鞘群算法-附代码
  • [ 一起学React系列 -- 8 ] React中的文件上传
  • [译] 理解数组在 PHP 内部的实现(给PHP开发者的PHP源码-第四部分)
  • 【剑指offer】让抽象问题具体化
  • gops —— Go 程序诊断分析工具
  • Java反射-动态类加载和重新加载
  • October CMS - 快速入门 9 Images And Galleries
  • SpringBoot几种定时任务的实现方式
  • XML已死 ?
  • 闭包,sync使用细节
  • 不上全站https的网站你们就等着被恶心死吧
  • 从@property说起(二)当我们写下@property (nonatomic, weak) id obj时,我们究竟写了什么...
  • 聚类分析——Kmeans
  • 开源SQL-on-Hadoop系统一览
  • 如何解决微信端直接跳WAP端
  • 小程序测试方案初探
  • 用element的upload组件实现多图片上传和压缩
  • MPAndroidChart 教程:Y轴 YAxis
  • 国内开源镜像站点
  • 湖北分布式智能数据采集方法有哪些?
  • 曾刷新两项世界纪录,腾讯优图人脸检测算法 DSFD 正式开源 ...
  • ​软考-高级-系统架构设计师教程(清华第2版)【第15章 面向服务架构设计理论与实践(P527~554)-思维导图】​
  • #pragma once
  • (1)Android开发优化---------UI优化
  • (C语言)深入理解指针2之野指针与传值与传址与assert断言
  • (NO.00004)iOS实现打砖块游戏(九):游戏中小球与反弹棒的碰撞
  • (ZT) 理解系统底层的概念是多么重要(by趋势科技邹飞)
  • (附源码)springboot太原学院贫困生申请管理系统 毕业设计 101517
  • (附源码)计算机毕业设计SSM基于健身房管理系统
  • (六)什么是Vite——热更新时vite、webpack做了什么
  • (十二)devops持续集成开发——jenkins的全局工具配置之sonar qube环境安装及配置
  • (转)LINQ之路
  • .net 使用ajax控件后如何调用前端脚本
  • .NET 中的轻量级线程安全
  • .NET成年了,然后呢?
  • .NET开源的一个小而快并且功能强大的 Windows 动态桌面软件 - DreamScene2
  • .NET框架类在ASP.NET中的使用(2) ——QA
  • /etc/fstab 只读无法修改的解决办法
  • /etc/skel 目录作用
  • @我的前任是个极品 微博分析
  • [ Linux Audio 篇 ] 音频开发入门基础知识