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

条件构造器算是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);
}


总结

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

  • 3
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

尹煜

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值