MybatisPlus(SpringBoot版)学习第五讲:条件构造器和常用接口
目录
1.wrapper介绍
2.QueryWrapper
2.1 例1:组转查询条件
Compare
Nested
Join
Func
2.2 例2:组装排序条件
2.3 例3:组装删除条件
2.4 例4:条件的优先级
2.5 例5:组装select子句
2.6 例6:实现子查询
3.UpdateWrapper
4.Condition
4.1 思路一
4.2 思路二:
5.LambdaQueryWrapper
6.LambdaUpdateWrapper
1.wrapper介绍
Wrapper : 条件构造抽象类,最顶端父类
AbstractWrapper : 用于查询条件封装,生成 sql 的 where 条件
QueryWrapper : 查询条件封装
UpdateWrapper : Update 条件封装
AbstractLambdaWrapper : 使用Lambda 语法
LambdaQueryWrapper :用于Lambda语法使用的查询Wrapper
LambdaUpdateWrapper : Lambda 更新封装Wrapper
ctrl+h
2.QueryWrapper
2.1 例1:组转查询条件
/***
* 按查询条件组装
*/
@Test
public void test01(){
QueryWrapper<People> queryWrapper=new QueryWrapper<>();
//SELECT id,username AS name,age,email,is_deleted
// FROM t_people
// WHERE is_deleted=0 AND (username LIKE ? AND age BETWEEN ? AND ? AND email IS NOT NULL)
queryWrapper.like("username","a")
.between("age",20,30)
.isNotNull("email");
List<People> list=peopleMapper.selectList(queryWrapper);
list.forEach(System.out::println);
}
QueryWrapper继承AbstractWrapper,我们点击AbstractWrapper进去看看。
我们能看到AbstrackWrapper实现了这四个接口。
Compare
- 作用:用于构建比较条件,比如等于(
eq
)、不等于(ne
)、大于(gt
)、小于(lt
)等条件。在构建 SQL 查询条件时,可用来描述实体属性和具体值之间的比较关系 。
Nested
- 作用:用于构建嵌套查询条件,当需要在查询条件中添加括号包裹的子条件时会用到。可以让查询条件的逻辑结构更清晰,实现复杂的条件组合。
Join
- 作用:主要用于处理 SQL 的连接操作,比如内连接(
INNER JOIN
)、左连接(LEFT JOIN
)等。在多表查询场景下,通过它来定义表与表之间的连接关系。
Func
- 作用:是一个函数式接口,通常用于封装一些可复用的条件构建逻辑。可以将条件构建的代码块作为参数传递,方便代码的复用和逻辑组织。
我们能够看到,他们都是默认的方法, 继承他的类可以直接使用这个方法,也可以进行重写。同IService原码
2.2 例2:组装排序条件
/***
* 按排序组装
*/
@Test
public void test02(){
QueryWrapper<People> queryWrapper=new QueryWrapper<>();
queryWrapper.orderByDesc("age")
.orderByAsc("id");
List<People> list=peopleMapper.selectList(queryWrapper);
list.forEach(System.out::println);
}
2.3 例3:组装删除条件
/***
* 组装删除条件
*/
@Test
public void test03(){
QueryWrapper<People> queryWrapper=new QueryWrapper<>();
queryWrapper.isNull("email");
int result=peopleMapper.delete(queryWrapper);
System.out.println("受影响的行数:"+result);
}
2.4 例4:条件的优先级
/***
* 优先级
*/
@Test
public void test04(){
QueryWrapper<People> queryWrapper=new QueryWrapper<>();
//UPDATE t_people SET age=?, email=?
// WHERE is_deleted=0 AND (username LIKE ? AND age > ? OR email IS NULL)
queryWrapper.like("username", "a")
.gt("age", 20)
.or()
.isNull("email");
People people=new People();
people.setAge(18);
people.setEmail("people@qcby.com");
int result=peopleMapper.update(people,queryWrapper);
System.out.println("受影响的行数:" + result);
}
lambda表达式里的逻辑优先算法
/***
* lambda表达式里的逻辑优先算法
*/
@Test
public void test05(){
QueryWrapper<People> queryWrapper=new QueryWrapper<>();
//UPDATE t_people SET age=?, email=?
// WHERE is_deleted=0 AND (username LIKE ? AND (age > ? OR email IS NULL))
queryWrapper.like("username",'a')
.and(i ->i.gt("age",20).or().isNull("email"));
People people=new People();
people.setAge(18);
people.setEmail("people@qcby.com");
int result=peopleMapper.update(people,queryWrapper);
System.out.println("受影响的行数:" + result);
}
2.5 例5:组装select子句
/***
* 组装select语句
*/
@Test
public void test06(){
//查询用户信息的username和age字段
//SELECT username,age FROM t_people
QueryWrapper<People> queryWrapper=new QueryWrapper<>();
queryWrapper.select("username","age");
//selectMaps()返回Map集合列表,通常配合select()使用,
// 避免People对象中没有被查询到的列值 为null
List<Map<String,Object>> maps=peopleMapper.selectMaps(queryWrapper);
maps.forEach(System.out::println);
}
2.6 例6:实现子查询
/***
* 实现子查询
*/
@Test
public void test07(){
//SELECT id,username AS name,age,email,is_deleted FROM t_people
// WHERE is_deleted=0 AND (id IN (select id from t_people where id<=3))
QueryWrapper<People> queryWrapper=new QueryWrapper<>();
queryWrapper.inSql("id","select id from t_people where id<=3");
List<People> list=peopleMapper.selectList(queryWrapper);
list.forEach(System.out::println);
}
3.UpdateWrapper
/***
* UpdateWrapper
*/
@Test
public void test08(){
//将(年龄大于20或邮箱为null)并且用户名中包含有a的用户信息修改
//组装set子句以及修改条件
UpdateWrapper<People> updateWrapper=new UpdateWrapper<>();
//lambda表达式内的逻辑优先运算
updateWrapper
.set("age", 18)
.set("email", "user@qcby.com")
.like("username", "a")
.and(i -> i.gt("age", 20).or().isNull("email"));
//UPDATE t_people SET age=?,email=?
// WHERE is_deleted=0 AND
// (username LIKE ? AND (age > ? OR email IS NULL))
int result = peopleMapper.update(null, updateWrapper);
System.out.println(result);
}
Lambda 表达式是 Java 8 引入的一个新特性,它可以让你以更简洁的方式表示一个匿名函数。
在这个例子中,i -> i.gt("age", 20).or().isNull("email")
表示一个接受一个参数 i
,并对其进行一系列操作的函数。
参数 i
通常是 MyBatis-Plus 中的 QueryWrapper
或者 UpdateWrapper
对象,它们用于构建 SQL 查询或者更新语句的条件部分。
4.Condition
在真正开发的过程中,组装条件是常见的功能,而这些条件数据来源于用户输入,是可选的,因 此我们在组装这些条件时,必须先判断用户是否选择了这些条件,若选择则需要组装该条件,若 没有选择则一定不能组装,以免影响SQL执行的结果
4.1 思路一
使用StringUtils的前提
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.12.0</version>
</dependency>
@Test
public void test09(){
//定义查询条件,有可能为null(用户未输入或未选择)
String username=null;
Integer ageBegin = 10;
Integer ageEnd = 24;
QueryWrapper<People> queryWrapper = new QueryWrapper<>();
//StringUtils.isNotBlank()判断某字符串是否不为空且长度不为0且不由空白符(whitespace) 构成
if(StringUtils.isNotBlank(username)){
queryWrapper.like("username","a");
}
if(ageBegin != null){
queryWrapper.ge("age", ageBegin);
}
if(ageEnd != null){
queryWrapper.le("age", ageEnd);
}
//SELECT id,username AS name,age,email,is_deleted FROM t_user WHERE (age >= ? AND age <= ?)
List<People> peoples = peopleMapper.selectList(queryWrapper);
peoples.forEach(System.out::println);
}
4.2 思路二:
上面的实现方案没有问题,但是代码比较复杂,我们可以使用带condition参数的重载方法构建查 询条件,简化代码的编写
@Test
public void test09UseCondition(){
//定义查询条件,有可能为null(用户未输入或未选择)
String username = null;
Integer ageBegin = 10;
Integer ageEnd = 24;
QueryWrapper<People> queryWrapper = new QueryWrapper<>();
//StringUtils.isNotBlank()判断某字符串是否不为空且长度不为0且不由空白符(whitespace) 构成
queryWrapper
.like(StringUtils.isNotBlank(username), "username", "a")
.ge(ageBegin != null, "age", ageBegin)
.le(ageEnd != null, "age", ageEnd);
//SELECT id,username AS name,age,email,is_deleted FROM t_user WHERE (age >= ? AND age <= ?)
List<People> peoples = peopleMapper.selectList(queryWrapper);
peoples.forEach(System.out::println);
}
5.LambdaQueryWrapper
/***
* LambdaQueryWrapper
*/
@Test
public void test10() {
//定义查询条件,有可能为null(用户未输入)
String username = "a";
Integer ageBegin = 10;
Integer ageEnd = 24;
LambdaQueryWrapper<People> queryWrapper = new LambdaQueryWrapper<>();
//避免使用字符串表示字段,防止运行时错误
queryWrapper
.like(StringUtils.isNotBlank(username), People::getName, username)
.ge(ageBegin != null, People::getAge, ageBegin)
.le(ageEnd != null, People::getAge, ageEnd);
//SELECT id,username AS name,age,email,is_deleted FROM t_people
// WHERE is_deleted=0 AND (username LIKE ? AND age >= ? AND age <= ?)
List<People> peoples = peopleMapper.selectList(queryWrapper);
peoples.forEach(System.out::println);
}
在 Java 里,People::getAge
属于方法引用的一种形式。方法引用是 Java 8 引入的特性,它能够让你直接引用已有的方法,而无需显式调用该方法。一般用于 Lambda 表达式能使用的地方,从而让代码更简洁。
6.LambdaUpdateWrapper
/***
* 使用LambdaUpdateWrapper
*/
@Test
public void test11(){
LambdaUpdateWrapper<People> updateWrapper=new LambdaUpdateWrapper<>();
//UPDATE t_people SET age=?, age=?,email=? WHERE is_deleted=0 AND (username LIKE ? AND (age < ? OR email IS NULL))
updateWrapper
.set(People::getAge,18)
.set(People::getEmail,"people@qcby.com")
.like(People::getName,"a")
.and(i ->i.lt(People::getAge,24).or().isNull(People::getEmail));//lambda 表达式内的逻辑优先运算
People people=new People();
int result=peopleMapper.update(people,updateWrapper);
System.out.println("受影响的行数:" + result);
}