【Java开发】 Mybatis-Plus 04:条件构造器-wrapper

2023-05-16

条件构造器算是Mybatis-Plus中很重要的知识点了,个人觉得它类似于Service的链式查询,将诸多条件集中在一个wrapper中,以达到高效便捷的目的。本文也是对01、02、03 内容的整合归纳,比较吃力的话建议看看前几章的内容哟~

目录

1 条件构造器介绍

2 QueryWrapper

2.1 普通使用1

2.2 普通使用2

2.3 模糊查询1

2.4 模糊查询2

2.5 子查询

2.6 查询排序

2.7 设置查询字段—select

3 UpdateWrapper

3.1 update

3.2 saveOrUpdate

3.3 set/setSql

4 LambdaWrapper

4.1 LambdaQueryWrapper

4.2 LambdaUpdateWrapper


 源码地址:尹煜 / mybatis_plus_study · GitCode

1 条件构造器介绍

在mybatis-plus中提了构造条件的类Wrapper,它可以根据自己的意图定义我们需要的条件。Wrapper是一个抽象类,一般情况下我们用它的子类QueryWrapper来实现自定义条件查询,用UpdateWrapper来实现自定义条件更新~

官方文档地址:条件构造器 | MyBatis-Plus

Mybatis Plus 提供的几种条件构造器,关系如下:

 LambdaQueryWrapper 与 QueryWrapper 的区别就在于前者是用函数式接口实现的(UpdateWrapper也是如此),如果不了解的同学可以点击该链接:lambda 表达式详解

警告:

  • 不支持以及不赞成在 RPC 调用中把 Wrapper 进行传输
  • 正确的 RPC 调用姿势是写一个 DTO 进行传输,被调用方再根据 DTO 执行相应的操作

接下来以一些实例来实现 Wrapper 的使用,若想要完整的方法,建议查阅官方文档~

QueryWrapper

QueryWrapper 匹配CRUD接口方法汇总!!

QueryWrapper 基本上都用在查询及删除等方法。

Mapper 接口👇

// 根据 entity 条件,删除记录
int delete(Wrapper<T> wrapper);
// 根据 entity 条件,查询一条记录
T selectOne(Wrapper<T> queryWrapper);
// 根据 entity 条件,查询全部记录
List<T> selectList(Wrapper<T> queryWrapper);
// 根据 Wrapper 条件,查询全部记录
List<Map<String, Object>> selectMaps( Wrapper<T> queryWrapper);
// 根据 Wrapper 条件,查询全部记录。注意: 只返回第一个字段的值
List<Object> selectObjs( Wrapper<T> queryWrapper);
// 根据 entity 条件,查询全部记录(并翻页)
IPage<T> selectPage(IPage<T> page,  Wrapper<T> queryWrapper);
// 根据 Wrapper 条件,查询全部记录(并翻页)
IPage<Map<String, Object>> selectMapsPage(IPage<T> page, Wrapper<T> queryWrapper);
// 根据 Wrapper 条件,查询总记录数
Integer selectCount( Wrapper<T> queryWrapper);

Service接口👇

// 根据 entity 条件,删除记录
boolean remove(Wrapper<T> queryWrapper);
// 根据 Wrapper,查询一条记录。结果集,如果是多个会抛出异常,随机取一条加上限制条件 wrapper.last("LIMIT 1")
T getOne(Wrapper<T> queryWrapper);
// 根据 Wrapper,查询一条记录
Map<String, Object> getMap(Wrapper<T> queryWrapper);
// 查询列表
List<T> list(Wrapper<T> queryWrapper);
// 查询列表
List<Map<String, Object>> listMaps(Wrapper<T> queryWrapper);
// 根据 Wrapper 条件,查询全部记录
List<Object> listObjs(Wrapper<T> queryWrapper);
// 条件分页查询
IPage<T> page(IPage<T> page, Wrapper<T> queryWrapper);
// 条件分页查询
IPage<Map<String, Object>> pageMaps(IPage<T> page, Wrapper<T> queryWrapper);
// 根据 Wrapper 条件,查询总记录数
int count(Wrapper<T> queryWrapper);

2.1 普通使用1

@Test
public void testQueryWrapper1() {
    //参数是一个wrapper ,条件构造器,和作为入参的map相似(如03-8)
    //查询name不为空,email不为空,age大于18的用户
    QueryWrapper<User> wrapper = new QueryWrapper<>();
    wrapper
            .isNotNull("name")
            .isNotNull("email")
            .ge("age",18);
    //userMapper用法:
    List<User> userList1 = userMapper.selectList(wrapper);
    //userService用法:
    List<User> userList2 = userService.list(wrapper);

    userList1.forEach(System.out::println);
}

2.2 普通使用2

@Test
public void testQueryWrapper2() {
    //查询name=wsk的用户
    QueryWrapper<User> wrapper = new QueryWrapper<>();
    wrapper.eq("name","尹煜");
    //查询一个数据selectOne,若查询出多个会报错
    //若出现多个结果使用list或map,比如userMapper.selectList()
    User user1 = userMapper.selectOne(wrapper);
    
    //userService用法:
    User user2 = userService.getOne(wrapper);
    
    System.out.println(user1);
}

2.3 模糊查询1

@Test
public void testQueryWrapper3() {
    //查询age在20-30之间的用户
    QueryWrapper<User> wrapper = new QueryWrapper<>();
    wrapper.between("age", 20, 30);//区间
    //userMapper用法:
    Long count1 = userMapper.selectCount(wrapper);//输出查询的数量selectCount

    //userService用法:
    long count2 = userService.count(wrapper);

    System.out.println(count1);
}

2.4 模糊查询2

@Test
public void testQueryWrapper4() {
    //模糊查询
    QueryWrapper<User> wrapper = new QueryWrapper<>();
    wrapper
            .notLike("name","t")//name中不包含
            .likeRight("email","y");//邮箱第一个值是y
    //userMapper用法:
    List<Map<String, Object>> maps1 = userMapper.selectMaps(wrapper);

    //userService用法:
    List<Map<String, Object>> maps2 = userService.listMaps(wrapper);

    maps1.forEach(System.out::println);
}

2.5 子查询

@Test
public void testQueryWrapper5() {
    //模糊查询
    // SELECT id,name,age,email,version,deleted,create_time,update_time
    //FROM user
    //WHERE deleted=0 AND id IN
    //(select id from user where id<5)
    QueryWrapper<User> wrapper = new QueryWrapper<>();
    //id 在子查询中查出来
    wrapper.inSql("id","select id from user where id<5");
    //userMapper用法:
    List<Object> objects1 = userMapper.selectObjs(wrapper);

    //userService用法:
    List<Object> objects2 = userService.listObjs(wrapper);

    objects1.forEach(System.out::println);
}

2.6 查询排序

@Test
public void testWrapper6() {
    QueryWrapper<User> wrapper = new QueryWrapper<>();
    //通过id进行降序排序
    wrapper.orderByDesc("id");
    //userMapper用法:
    List<User> userList1 = userMapper.selectList(wrapper);

    //userService用法:
    List<User> userList2 = userService.list(wrapper);

    userList1.forEach(System.out::println);
}

2.7 设置查询字段—select

@Test
public void testQueryWrapper7() {
    //参数是一个wrapper ,条件构造器,和刚才的map对比学习!
    //查询name不为空,email不为空,age大于18的用户
    QueryWrapper<User> wrapper = new QueryWrapper<>();
    wrapper
            .isNotNull("name")
            .isNotNull("email")
            .ge("age",18)
            .select("name","age")//查询name、age字段的数值
            .select(User.class,i -> i.getColumn().startsWith("n"));//查询以n开头的字段名的数值
    //userMapper用法:
    List<User> userList1 = userMapper.selectList(wrapper);

    //userService用法:
    List<User> userList2 = userService.list(wrapper);

    userList1.forEach(System.out::println);
}

MyBatisPlus 其实进行了两次查询,以最后一次为准,只返回指定字段的数值(id是主键所以也会返回)!

UpdateWrapper

UpdateWrapper 匹配CRUD接口方法汇总!!

不过搭配 UpdateWrapper 的方法不多😂

Mapper 接口👇

// 根据 whereWrapper 条件,更新记录
int update( T Entity, Wrapper<T> updateWrapper);

Service接口👇

// 根据updateWrapper尝试更新,否继续执行saveOrUpdate(T)方法
boolean saveOrUpdate(T entity, Wrapper<T> updateWrapper);
// 根据 updateWrapper条件,更新记录
boolean update(T entity, Wrapper<T> updateWrapper);
// 根据 updateWrapper条件,更新记录
boolean update(Wrapper<T> updateWrapper);//需要用到set/setSql

3.1 update

和 Service 接口的 UpdateChainWrapper 一样,不论存不存在主键 id ,只要满足updatewrapper 条件的记录都会更新成模板实体类的形式!

@Test
public void testUpdateWrapper1() {
    User user = User.builder().id(1L).name("saveBatch1").age(15).email("yinyu@163.com").build();
    UpdateWrapper<User> updatewrapper = new UpdateWrapper<>();
    updatewrapper
            .isNotNull("name")
            .ge("age",18)
            .set("name","尹煜");//数据库字段值变为尹煜
    //userMapper用法:
    int result1 = userMapper.update(user,updatewrapper);

    //userService用法:
    boolean result2 = userService.update(user,updatewrapper);

    System.out.println(result1);
}

更新前:

  更新后:id=7没更新是因为已经逻辑删除

3.2 saveOrUpdate

这个方法的逻辑是:

对于满足 UpdateWrapper 条件的记录:

实体类不论是否存在主键id,所有满足 UpdateWrapper 条件的记录都会更新成实体类的形式。

若没有记录满足 UpdateWrapper 条件:

若存在主键,执行查找,若根据主键查询成功则执行更新,若根据主键查询失败(也就是id不存在)则执行插入,若不存在主键,直接执行插入。

①有记录满足 UpdateWrapper 条件,存在主键 id

@Test
public void testUpdateWrapper2() {
    User user = User.builder().name(1L).name("尹煜").age(18).email("yinyu@163.com").build();
    UpdateWrapper<User> updatewrapper = new UpdateWrapper<>();
    updatewrapper
            .isNotNull("name")
            .ge("age",150);//年龄大于150

    boolean result1 = userService.saveOrUpdate(user,updatewrapper);

    System.out.println(result1);
}

更新前:

更新后:

②若没有记录满足 UpdateWrapper 条件,不存在主键 id

@Test
public void testUpdateWrapper2() {
    User user = User.builder().name("testUpdateWrapper22").age(18).email("yinyu@163.com").build();
    UpdateWrapper<User> updatewrapper = new UpdateWrapper<>();
    updatewrapper
            .isNotNull("name")
            .ge("age",200);//年龄大于200,没有满足条件的记录

    boolean result1 = userService.saveOrUpdate(user,updatewrapper);

    System.out.println(result1);
}

新增数据:

3.3 set/setSql

有时会觉得既要写实体类,又要写 updatewrapper 太麻烦了,MyBatisPlus也为 updatewrapper  提供了 set/setSql 方法,实在考虑到了每个懒人的想法,只需要写 updatewrapper  就行了!

@Test
public void testUpdateWrapper3() {
    UpdateWrapper<User> updatewrapper = new UpdateWrapper<>();
    updatewrapper
            .isNotNull("name")
            .ge("age",18)//年龄大于等于18
            .set("name","尹煜1")//数据库字段name设为尹煜
            .setSql("age = 20");//数据库字段age设为20

    boolean result2 = userService.update(updatewrapper);
}

更新前: 

更新后:

LambdaWrapper

其实 LambdaWrapper 和 Wrapper 的用法是一致的,只不过写法不一样,LambdaWrapper 用的是函数式接口,下边就举几个简单的例子~

4.1 LambdaQueryWrapper

@Test
public void LambdaQueryWrapper() {
    //参数是一个wrapper ,条件构造器,和作为入参的map相似(如03-8)
    //查询name不为空,email不为空,age大于18的用户
    LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>();
    wrapper
            .isNotNull(User::getAge)//用法1
            .isNotNull(user -> user.getEmail())//用法2,不过官方推荐用法1
            .ge(User::getAge,18);
    //userMapper用法:
    List<User> userList1 = userMapper.selectList(wrapper);
    //userService用法:
    List<User> userList2 = userService.list(wrapper);

    userList1.forEach(System.out::println);
}

4.2 LambdaUpdateWrapper

@Test
public void LambdaUpdateWrapper() {
    LambdaUpdateWrapper<User> updatewrapper = new LambdaUpdateWrapper<>();
    //通过id进行降序排序
    updatewrapper
            .isNotNull(User::getName)//name不为空
            .lt(User::getAge,20)//年龄小于20
            .set(User::getName,"尹煜");//设置name为尹煜,不设置的话会报错!

    boolean result2 = userService.update(updatewrapper);

    System.out.println(result2);
}


总结

大家如果有疑问都可以评论提出,有不足之处请大家批评指正,希望能多结识这方面的朋友,共同学习、共同进步。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

【Java开发】 Mybatis-Plus 04:条件构造器-wrapper 的相关文章

随机推荐

  • python3字符串

    Python3 字符串 字符串是 Python 中最常用的数据类型 我们可以使用引号 或 来创建字符串 创建字符串很简单 xff0c 只要为变量分配一个值即可 例如 xff1a var1 61 Hello World var2 61 Run
  • html思维导图

    标题标签 标题标签 h1 h5 xff0c 字体从大到小 对应英文语义headline 使用注意 xff1a 标题里的文字要xian想水平居中或者垂直居中得用text align和line height来做 xff0c 内外边距不行 xff
  • 什么是MVVM?

    什么是MVVM MVVM是Model View ViewModel的缩写 MVVM是一种设计思想 View层是视图层 xff0c 也就是用户界面 前端主要由HTML和CSS来构建 xff1b Model层 是指数据模型 xff0c 泛指后端
  • Docker——Windows版本Docker安装

    目录 一 简介 1 1 Docker如何解决大型项目依赖关系复杂 xff0c 不同组件依赖的兼容性问题 xff1f 1 2 Docker如何解决开发 测试 生产环境有差异的问题 1 3 Docker 和 虚拟机的区别 1 4 Docker架
  • 细说C++中的 :: 和 : 的区别

    C 43 43 中的 1 类的作用域 作用域符号 的前面一般是类名称 xff0c 后面一般是该类的成员名称 xff0c C 43 43 为例避免不同的类有名称相同的成员而采用作用域的方式进行区分 假如 xff1a A B表示两个类 xff0
  • 扰动观测器(DOB)设计

    snf 机器人机械手可能会受到不同类型的干扰 例如未知的有效载荷 未建模的动力学和环境相互作用力 观察机器人操纵器中的这些未知干扰是许多机器人应用的基础 例如干扰抑制和无传感器力控制 机械手在进行正常操作时可能会受到不同类型的干扰 粗略地说
  • Gazebo安装教程——在 Ubuntu 上安装Gazebo的源代码

    安装工具 建议使用一些额外的工具来帮助编译源代码 xff0c 尽管其他正确获取和构建源代码的方法也是可能的 获取所有库的源代码的最简单方法是使用 vcstool 要以正确的顺序编译所有不同的库和 ign gazebo xff0c 建议使用c
  • 线性与非线性控制

    控制理论领域可以分为两个分支 xff1a 线性控制理论 这适用于由遵循叠加原理的设备组成的系统 xff0c 这大致意味着输出与输入成正比 它们由线性微分方程控制 一个主要的子类是另外具有不随时间变化的参数的系统 xff0c 称为线性时不变
  • 模型预测控制(Model predictive control,MPC)

    模型预测控制 MPC 是一种先进的过程控制方法 xff0c 用于在满足一组约束条件的同时控制过程 自 1980 年代以来 xff0c 它一直在化工厂和炼油厂的加工工业中使用 近年来 xff0c 它还被用于电力系统平衡模型 1 和电力电子学中
  • 蓝桥杯单片机官方测试程序现象

    IO模式 xff0c 矩阵按键下 xff1a 开机次数 测试AT24C02 S7 测试LED 按2次 S11 测试DAC 按4次 S15 测试ADC双通道 按2次 S19 测试超声波 S6 测试温度模块 S10 0 测量 S14 测试继电器
  • 51单片机的1T和12T的区别

    1T 模式 不分频 1个系统基本时钟 xff0c 执行一个动作 xff1b 12T模式 12分频 12个系统基本时钟 xff0c 执行一个动作 xff1b 因此 xff0c 12T模式和1T模式执行相同次数的动作 xff0c 12T模式需要
  • python2数据类型

    Python3 数字 Number Python 数字数据类型用于存储数值 数据类型是不允许改变的 这就意味着如果改变数字数据类型得值 xff0c 将重新分配内存空间 以下实例在变量赋值时 Number 对象将被创建 xff1a var1
  • keil中的extern的使用

    C51头文件使用extern的目的是外部变量或函数声明 使用时要注意 1 extern最好写在 h文件中 xff0c 方便后期的可读性 2 在使用extern进行外部变量声明时 xff0c 不能重新给变量赋值 例如 xff1a extern
  • STC89C52RC/RD中定时器2的使用方法

    学过一段时间单片机的你发现 xff0c 中断服务函数可以在主函数进行的同时 xff0c 进行一些对时间要求高的模块的配置时 xff0c 则要用到定时器中断 而如果你要实现多个功能的操作 xff0c 会使用多个定时器是必要的STC89C51单
  • keilC51中调试的方法(主要介绍串口调试XCOM)

    在keilC51中调试的方法的方法有很多 xff1a 1 直接看现象 2 串口调试 3 debug调试 下面终点讲串口调试 xff1a 若要实现printf重定向 重写printf调用的putchar函数 xff0c 重定向到串口输出 需要
  • data/xdata/pdata/code

    dada最大在128byte xff0c 不然就会报错 data xdada最大在512byte xff0c 不然就会报错 xdata pdata stc89c52中未使用 code xff08 将ROM内的定值存在程序存储器中 xff0c
  • 基于PID算法(python)的飞控设计学习日志(一)

    PID算法基础 首先我们需要去了解PID算法的数学原理 xff0c 数学原理部分借鉴于 64 确定有穷自动 机 的博客 一文读懂PID控制算法 xff08 抛弃公式 xff0c 从原理上真正理解PID控制 xff09 总的来说 xff0c
  • JAVA- 浅谈==与equal()的区别

    目录 gt 基础 gt 基本数据类型 gt 引用数据类型 gt Java内存 gt 区别 61 61 和equals gt 61 61 gt equals gt 总结 gt 基础 要想区分这两者 xff0c 我们得先明白什么是基本数据类型和
  • Ubuntu20.04+RealSense D455

    Ubuntu20 04装RealSense D455的驱动 Ubuntu20 04装RealSense D455的驱动 官网链接和个人链接 官网链接和个人链接 前言 xff1a 这些是我ubuntu20 04安装时候所找到的方法 xff0c
  • 【Java开发】 Mybatis-Plus 04:条件构造器-wrapper

    条件构造器算是Mybatis Plus中很重要的知识点了 xff0c 个人觉得它类似于Service的链式查询 xff0c 将诸多条件集中在一个wrapper中 xff0c 以达到高效便捷的目的 本文也是对01 02 03 内容的整合归纳