条件构造器算是Mybatis-Plus中很重要的知识点了,个人觉得它类似于Service的链式查询,将诸多条件集中在一个wrapper中,以达到高效便捷的目的。本文也是对01、02、03 内容的整合归纳,比较吃力的话建议看看前几章的内容哟~
目录
源码地址:尹煜 / 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 的使用,若想要完整的方法,建议查阅官方文档~
2 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是主键所以也会返回)!
3 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);
}
更新前:
更新后:
4 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);
}
总结
大家如果有疑问都可以评论提出,有不足之处请大家批评指正,希望能多结识这方面的朋友,共同学习、共同进步。