MyBatisPlus条件构造器
在前面章节中,我们用到了不少条件构造器,本章介绍下MyBatisPlus中提供的条件构造器有哪些。
# 1、条件构造器关系
类关系图
- AbstractWrapper是QueryWrapper(LambdaQueryWrapper) 和 UpdateWrapper(LambdaUpdateWrapper) 的父类。
- 常用:QueryWrapper(LambdaQueryWrapper) 和 UpdateWrapper(LambdaUpdateWrapper)
# 2、AbstractWrapper
- AbstractWrapper为条件构造器的抽象类,它提供很多条件方法。
- AbstractWrapper是QueryWrapper(LambdaQueryWrapper) 和 UpdateWrapper(LambdaUpdateWrapper) 的父类。
- 用于生成 sql 的 where 条件, entity 属性也用于生成 sql 的 where 条件
- 注意: entity 生成的 where 条件与 使用各个 api 生成的 where 条件没有任何关联行为
# 2.1、使用案例
@Test
public void testQuery9(){
// 查询id小于20
List<StudentPO> list = studentService.list(new LambdaQueryWrapper<StudentPO>().le(StudentPO::getId, 20));
log.info("list========>"+list);
}
2
3
4
5
6
# 2.2、AbstractWrapper方法
方法名 | 描述 | 案例说明 |
---|---|---|
allEq | 查询字段值全部相等的记录。 | allEq案例 |
eq | 查询字段值等于给定值的记录。 | eq("name", "老王")--->name = '老王' |
ne | 查询字段值不等于给定值的记录。 | ne("name", "老王")--->name <> '老王' |
gt | 查询字段值大于给定值的记录。 | gt("age", 18)--->age > 18 |
ge | 查询字段值大于等于给定值的记录。 | ge("age", 18)--->age >= 18 |
lt | 查询字段值小于给定值的记录。 | lt("age", 18)--->age < 18 |
le | 查询字段值小于等于给定值的记录。 | le("age", 18)--->age <= 18 |
between | 查询字段值在两个值之间的记录。 | between("age", 18, 30)--->age between 18 and 30 |
notBetween | 查询字段值不在两个值之间的记录。 | notBetween("age", 18, 30)--->age not between 18 and 30 |
like | 查询字段值包含给定值的记录。 | like("name", "王")--->name like '%王%' |
notLike | 查询字段值不包含给定值的记录。 | notLike("name", "王")--->name not like '%王%' |
likeLeft | 查询字段值以给定值开头的记录。 | likeLeft("name", "王")--->name like '%王' |
likeRight | 查询字段值以给定值结尾的记录。 | likeRight("name", "王")--->name like '王%' |
notLikeLeft | 查询字段值不以给定值开头的记录。 | notLikeLeft("name", "王")--->name not like '%王' |
notLikeRight | 查询字段值不以给定值结尾的记录。 | notLikeRight("name", "王")--->name not like '王%' |
isNull | 查询字段值为null的记录。 | isNull("name")--->name is null |
isNotNull | 查询字段值不为null的记录。 | isNotNull("name")--->name is not null |
in | 查询字段值在给定集合中的记录。 | 例1: in("age",{1,2,3})--->age in (1,2,3) 例2: in("age", 1, 2, 3)--->age in (1,2,3) |
notIn | 查询字段值不在给定集合中的记录。 | 例1: notIn("age",{1,2,3})--->age not in (1,2,3) 例2: notIn("age", 1, 2, 3)--->age not in (1,2,3) |
inSql | 生成SQL中的IN子句,用于查询。注意:这可能会增加SQL注入的风险,应谨慎使用。 | 例1: inSql("age", "1,2,3,4,5,6")--->age in (1,2,3,4,5,6) 例2: inSql("id", "select id from table where id < 3")--->id in (select id from table where id < 3) |
notInSql | 生成SQL中的NOT IN子句,用于查询。同样,注意SQL注入的风险。 | 例1: notInSql("age", "1,2,3,4,5,6")--->age not in (1,2,3,4,5,6) 例2: notInSql("id", "select id from table where id < 3")--->id not in (select id from table where id < 3) |
groupBy | 指定SQL的GROUP BY子句。 | groupBy("id", "name")--->group by id,name |
orderByAsc | 指定SQL的ORDER BY子句,升序排列。 | orderByAsc("id", "name")--->order by id ASC,name ASC |
orderByDesc | 指定SQL的ORDER BY子句,降序排列。 | rderByDesc("id", "name")--->order by id DESC,name DESC |
orderBy | 指定SQL的ORDER BY子句,可指定排序方式。 | orderBy(true, true, "id", "name")--->order by id ASC,name ASC |
having | 指定SQL的HAVING子句,通常与GROUP BY配合使用。 | 例1: having("sum(age) > 10")--->having sum(age) > 10 例2: having("sum(age) > {0}", 11)--->having sum(age) > 11 |
func | 调用数据库函数或方法。 | func(i -> if(true) {i.eq("id", 1)} else {i.ne("id", 1)}) |
or | 表示SQL中的OR逻辑操作。 | 例1: eq("id",1).or().eq("name","老王")--->id = 1 or name = '老王' 例2: or(i -> i.eq("name", "李白").ne("status", "活着"))--->or (name = '李白' and status <> '活着') |
and | 表示SQL中的AND逻辑操作。 | and(i -> i.eq("name", "李白").ne("status", "活着"))--->and (name = '李白' and status <> '活着') |
nested | 表示嵌套条件,常用于构建复杂的查询条件。 | nested(i -> i.eq("name", "李白").ne("status", "活着"))--->(name = '李白' and status <> '活着') |
apply | 用于构建SQL的动态WHERE子句,更灵活地拼接条件。 | apply案例 |
last | 用于手动拼接SQL片段,通常在链式调用中结束时使用。 | last案例 |
exists | 表示子查询存在时返回true,常用于EXISTS条件。 | exists("select id from table where age = 1")--->exists (select id from table where age = 1) |
notExists | 表示子查询不存在时返回true,常用于NOT EXISTS条件。 | notExists("select id from table where age = 1")--->not exists (select id from table where age = 1) |
# 2.3、✨案例说明
# allEq案例
全部eq(或个别isNull)
个别参数说明:
- params : key为数据库字段名,value为字段值
- null2IsNull : 为true则在map的value为null时调用 isNull 方法,为false时则忽略value为null的
allEq(BiPredicate<R, V> filter, Map<R, V> params)
allEq(BiPredicate<R, V> filter, Map<R, V> params, boolean null2IsNull)
allEq(boolean condition, BiPredicate<R, V> filter, Map<R, V> params, boolean null2IsNull)
2
3
- 例1:
allEq({id:1,name:"老王",age:null})--->id = 1 and name = '老王' and age is null
- 例2:
allEq({id:1,name:"老王",age:null}, false)--->id = 1 and name = '老王'
个别参数说明:
- filter : 过滤函数,是否允许字段传入比对条件中
- params 与 null2IsNull : 同上
- 例1:
allEq((k,v) -> k.contains("a"), {id:1,name:"老王",age:null})--->name = '老王' and age is null
- 例2:
allEq((k,v) -> k.contains("a"), {id:1,name:"老王",age:null}, false)--->name = '老王'
# apply案例
拼接 sql
apply(String applySql, Object... params)
apply(boolean condition, String applySql, Object... params)
2
注意事项
该方法可用于数据库函数 动态入参的params对应前面applySql内部的{index}部分.这样是不会有sql注入风险的,反之会有!
- 例:
apply("id = 1")--->id = 1
- 例:
apply("date_format(dateColumn,'%Y-%m-%d') = '2008-08-08'")--->date_format(dateColumn,'%Y-%m-%d') = '2008-08-08'")
- 例:
apply("date_format(dateColumn,'%Y-%m-%d') = {0}", "2008-08-08")--->date_format(dateColumn,'%Y-%m-%d') = '2008-08-08'")
# last案例
无视优化规则直接拼接到 sql 的最后
last(String lastSql)
last(boolean condition, String lastSql)
2
注意事项
只能调用一次,多次调用以最后一次为准 有sql注入的风险,请谨慎使用
例: last("limit 1")
# 3、QueryWrapper
说明
继承自 AbstractWrapper ,自身的内部属性 entity 也用于生成 where 条件,及 LambdaQueryWrapper, 可以通过 new QueryWrapper().lambda() 方法获取
QueryWrapper 除了 AbstractWrapper中的方法,还提供了一个select的方法:
select(String... sqlSelect)
select(Predicate<TableFieldInfo> predicate)
select(Class<T> entityClass, Predicate<TableFieldInfo> predicate)
2
3
案例
- 例: select("id", "name", "age")
- 例: select(i -> i.getProperty().startsWith("test"))
@SpringBootTest
@Slf4j
public class TestController {
@Autowired
private StudentServiceImpl studentService;
@Test
public void testQuery(){
// 只查询 id 和 name 字段
Wrapper<StudentPO> wrapper = new QueryWrapper<StudentPO>().select("id", "name")).eq("name", "ls");
List<StudentPO> list = studentService.list(wrapper);
log.info("studentList========>"+list);
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 4、UpdateWrapper
说明
继承自 AbstractWrapper ,自身的内部属性 entity 也用于生成 where 条件,及 LambdaUpdateWrapper, 可以通过 new UpdateWrapper().lambda() 方法获取!
UpdateWrapper 除了 AbstractWrapper 中的方法,还提供了一个其他几个方法:
# 4.1、set
set(String column, Object val)
set(boolean condition, String column, Object val)
2
案例
- 例: set("name", "老李头")
- 例: set("name", "")--->数据库字段值变为空字符串
- 例: set("name", null)--->数据库字段值变为null
@Test
public void tesUpdate(){
Wrapper<StudentPO> wrapper = new UpdateWrapper<StudentPO>().set("name","ss");
StudentPO studentPO = new StudentPO();
studentPO.setName("kk");
studentService.update(studentPO,wrapper);
}
2
3
4
5
6
7
8
9
# 4.2、setSql
setSql(String sql)
- 设置 SET 部分 SQL
- 例: setSql("name = '老李头'")
# 4.3、lambda
获取 LambdaWrapper
- 在QueryWrapper中是获取LambdaQueryWrapper
- 在UpdateWrapper中是获取LambdaUpdateWrapper
LambdaQueryWrapper<StudentPO> lambda1 = new QueryWrapper<StudentPO>().lambda();
LambdaUpdateWrapper<StudentPO> lambda2 = new UpdateWrapper<StudentPO>().lambda();
2
# 5、使用 Wrapper 自定义SQL
# 5.1、注解方式
需要mybatis-plus版本 >= 3.0.7
param 参数名要么叫ew,要么加上注解@Param(Constants.WRAPPER) 使用${ew.customSqlSegment} 不支持 Wrapper 内的entity生成where语句
// StudentMapper中增加方法
@Select("select * from student ${ew.customSqlSegment}")
List<StudentPO> selectAllStudent(@Param(Constants.WRAPPER) Wrapper wrapper);
// 测试
@Test
public void testQuery10(){
List<StudentPO> list = studentMapper.selectAllStudent(new LambdaQueryWrapper<StudentPO>().eq(StudentPO::getName, "ls"));
log.info("list========>"+list);
}
// 执行SQL:select * from student WHERE (name = 'ls')
2
3
4
5
6
7
8
9
10
11
12
13
# 5.2、XML方式
StudentMapper中增加方法
List<StudentPO> selectAllStudent(Wrapper wrapper);
在Mapper.xml中使用
<select id="selectAllStudent" resultType="StudentPO">
SELECT * FROM student ${ew.customSqlSegment}
</select>
2
3
结果和注解方式一样