当前位置: 首页 > 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飞行策略的改进樽海鞘群算法-附代码
  • 时间复杂度分析经典问题——最大子序列和
  • “大数据应用场景”之隔壁老王(连载四)
  • 2018一半小结一波
  • CoolViewPager:即刻刷新,自定义边缘效果颜色,双向自动循环,内置垂直切换效果,想要的都在这里...
  • emacs初体验
  • es6--symbol
  • Java-详解HashMap
  • leetcode386. Lexicographical Numbers
  • Mysql数据库的条件查询语句
  • nginx 配置多 域名 + 多 https
  • open-falcon 开发笔记(一):从零开始搭建虚拟服务器和监测环境
  • 关于for循环的简单归纳
  • 机器人定位导航技术 激光SLAM与视觉SLAM谁更胜一筹?
  • 理解IaaS, PaaS, SaaS等云模型 (Cloud Models)
  • 前端存储 - localStorage
  • 区块链将重新定义世界
  • 让你的分享飞起来——极光推出社会化分享组件
  • 十年未变!安全,谁之责?(下)
  • ​软考-高级-信息系统项目管理师教程 第四版【第14章-项目沟通管理-思维导图】​
  • #!/usr/bin/python与#!/usr/bin/env python的区别
  • ## 临床数据 两两比较 加显著性boxplot加显著性
  • (3)STL算法之搜索
  • (33)STM32——485实验笔记
  • (附源码)springboot猪场管理系统 毕业设计 160901
  • (汇总)os模块以及shutil模块对文件的操作
  • (三)Hyperledger Fabric 1.1安装部署-chaincode测试
  • (十) 初识 Docker file
  • (十八)三元表达式和列表解析
  • (四)Tiki-taka算法(TTA)求解无人机三维路径规划研究(MATLAB)
  • (一一四)第九章编程练习
  • (转)菜鸟学数据库(三)——存储过程
  • .mkp勒索病毒解密方法|勒索病毒解决|勒索病毒恢复|数据库修复
  • .NET 4.0中的泛型协变和反变
  • .NET MVC之AOP
  • .NET/C# 使用 #if 和 Conditional 特性来按条件编译代码的不同原理和适用场景
  • .Net各种迷惑命名解释
  • .NET中统一的存储过程调用方法(收藏)
  • [ C++ ] STL_list 使用及其模拟实现
  • [Android]Android P(9) WIFI学习笔记 - 扫描 (1)
  • [C++]C++类基本语法