14.Mybatis-Plus入门系列(14)- MybatisPlus之条件构造器
14.Mybatis-Plus入门系列(14)- MybatisPlus之条件构造器
前言
mybatis-plus提供了强大的条件构造器,用于构造Where条件。
Wrapper 条件构造抽象类
-- AbstractWrapper 查询条件封装,用于生成 sql 中的 where 语句。
-- QueryWrapper Query封装操作类,用于查询。
-- UpdateWrapper Update条件封装操作类,用于更新。
-- AbstractLambdaWrapper 使用 Lambda 表达式封装 wrapper
-- LambdaQueryWrapper 使用 Lambda 语法封装条件,用于查询。
-- LambdaUpdateWrapper 使用 Lambda 语法封装条件,用于更新。
AbstractWrapper
QueryWrapper(LambdaQueryWrapper) 和 UpdateWrapper(LambdaUpdateWrapper) 的父类用于生成 sql 的 where 条件, entity 属性也用于生成 sql 的 where 条件。
案例演示
以下案例全部采用Lambda表达式,这样
allEq
全部eq(或个别isNull)。
allEq(Map<R, V> params)
allEq(Map<R, V> params, boolean null2IsNull)
allEq(boolean condition, Map<R, V> params, boolean null2IsNull)
参数说明:
params : key为数据库字段名,value为字段值
null2IsNull : 为true则在map的value为null时调用 isNull 方法,为false时则忽略value为null的
condition: 该条件是否加入最后生成的sql中
案例演示:
@Test
public void allEqTest() {
System.out.println("----- allEq ------");
LambdaQueryWrapper<OrderTbl> queryWrapper = Wrappers.lambdaQuery();
Map<SFunction<OrderTbl, ?>,Object> params = new HashMap<>();
params.put(OrderTbl::getUserId, 123);
params.put(OrderTbl::getCount, 0);
// allEq(Map<R, V> params)
// queryWrapper.allEq(params);
// SELECT id,user_id,commodity_code,count,money,dept_id,tenant_id,is_deleted,version,oper_user,gmt_create,gmt_modified FROM order_tbl WHERE is_deleted=0 AND (count = 0 AND user_id = 123)
params.put(OrderTbl::getCommodityCode, null);
// allEq(Map<R, V> params, boolean null2IsNull)
// queryWrapper.allEq(params,true);
// SELECT id,user_id,commodity_code,count,money,dept_id,tenant_id,is_deleted,version,oper_user,gmt_create,gmt_modified FROM order_tbl WHERE is_deleted=0 AND (count = 0 AND user_id = 123 AND commodity_code IS NULL)
// allEq(boolean condition, Map<R, V> params, boolean null2IsNull)
boolean condition=false; // 条件
queryWrapper.allEq(condition,params,true);
// SELECT id,user_id,commodity_code,count,money,dept_id,tenant_id,is_deleted,version,oper_user,gmt_create,gmt_modified FROM order_tbl WHERE is_deleted=0
List<OrderTbl> list = orderTblService.list(queryWrapper);
}
使用BiPredicate函数式接口test()方法对params进行过滤,K为键,V为值,可以自定义过滤,返回false时,该KV将被移出params。
public <V> Children allEq(boolean condition, BiPredicate<R, V> filter, Map<R, V> params, boolean null2IsNull) {
if (condition && CollectionUtils.isNotEmpty(params)) {
params.forEach((k, v) -> {
if (filter.test(k, v)) {
if (StringUtils.checkValNotNull(v)) {
this.eq(k, v);
} else if (null2IsNull) {
this.isNull(k);
}
}
});
}
return this.typedThis;
}
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)
参数说明:
filter : 过滤函数,是否允许字段传入比对条件中
params、null2IsNull、condition : 同上
案例演示 :
只演示第一个,其他两个和上面一样,注意不能使用lambdaQuery,否则会导致无法过滤K。
@Test
public void allEqTest02() {
System.out.println("----- allEq ------");
QueryWrapper<OrderTbl> queryWrapper = Wrappers.query();
Map<String, Object> params = new HashMap<>();
params.put("user_id", "123");
params.put("count", 0);
queryWrapper.allEq((k, v) -> {
// 此处表示params中键为user_id 并且值为"123"的参数才添加到条件中
return "user_id".equals(k) && "123".equals(v);
}, params);
List<OrderTbl> list = orderTblService.list(queryWrapper);
}
eq
等于 =
eq(R column, Object val)
eq(boolean condition, R column, Object val)
参数说明:
column: 字段
val:字段值
condition : 该条件是否加入最后生成的sql中
案例演示:
@Test
public void eqTest02() {
System.out.println("----- eq ------");
LambdaQueryWrapper<OrderTbl> queryWrapper = Wrappers.lambdaQuery();
//queryWrapper.eq(OrderTbl::getUserId,123); // AND (user_id = 123)
queryWrapper.eq(true,OrderTbl::getUserId,123);
List<OrderTbl> list = orderTblService.list(queryWrapper);
}
ne
不等于 <>,参数同上。
ne(R column, Object val)
ne(boolean condition, R column, Object val)
案例演示:
@Test
public void neTest02() {
System.out.println("----- ne ------");
LambdaQueryWrapper<OrderTbl> queryWrapper = Wrappers.lambdaQuery();
//queryWrapper.ne(OrderTbl::getUserId,123); // AND (user_id <> 123)
queryWrapper.ne(true,OrderTbl::getUserId,123);
List<OrderTbl> list = orderTblService.list(queryWrapper);
}
gt
大于 >,参数同上
案例演示:
@Test
public void gtTest02() {
System.out.println("----- gt ------");
LambdaQueryWrapper<OrderTbl> queryWrapper = Wrappers.lambdaQuery();
//queryWrapper.gt(OrderTbl::getId,999999); // AND (id > 999999)
queryWrapper.gt(true,OrderTbl::getId,999999);
List<OrderTbl> list = orderTblService.list(queryWrapper);
}
ge
大于等于 >=,参数同上
ge(R column, Object val)
ge(boolean condition, R column, Object val)
案例演示:
@Test
public void geTest02() {
System.out.println("----- ge ------");
LambdaQueryWrapper<OrderTbl> queryWrapper = Wrappers.lambdaQuery();
queryWrapper.ge(OrderTbl::getGmtCreate,new Date()); // AND (gmt_create >= '2021-04-20T23:22:30.325+0800')
//queryWrapper.ge(true,OrderTbl::getGmtCreate,new Date());
List<OrderTbl> list = orderTblService.list(queryWrapper);
}
lt
小于 <,参数同上
lt(R column, Object val)
lt(boolean condition, R column, Object val)
案例演示:
@Test
public void ltTest02() {
System.out.println("----- lt ------");
LambdaQueryWrapper<OrderTbl> queryWrapper = Wrappers.lambdaQuery();
queryWrapper.lt(OrderTbl::getMoney,1000); // AND (money < 1000)
queryWrapper.lt(true,OrderTbl::getMoney,1000);
List<OrderTbl> list = orderTblService.list(queryWrapper);
}
le
小于等于 <=,参数同上
le(R column, Object val)
le(boolean condition, R column, Object val)
案例演示:
@Test
public void leTest02() {
System.out.println("----- le ------");
LambdaQueryWrapper<OrderTbl> queryWrapper = Wrappers.lambdaQuery();
queryWrapper.le(OrderTbl::getMoney,1000); // AND (money <= 1000)
//queryWrapper.le(true,OrderTbl::getMoney,1000);
List<OrderTbl> list = orderTblService.list(queryWrapper);
}
between
BETWEEN 值1 AND 值2,
between(R column, Object val1, Object val2)
between(boolean condition, R column, Object val1, Object val2)
参数说明:
column: 字段
val1:BETWEEN起始值,
val2:BETWEEN结束值,
condition : 该条件是否加入最后生成的sql中
案例演示:
@Test
public void betweenTest02() {
System.out.println("----- between ------");
LambdaQueryWrapper<OrderTbl> queryWrapper = Wrappers.lambdaQuery();
queryWrapper.between(OrderTbl::getMoney,500,800); // AND (money BETWEEN 500 AND 800)
//queryWrapper.between(true,OrderTbl::getMoney,500,800);
List<OrderTbl> list = orderTblService.list(queryWrapper);
}
notBetween
NOT BETWEEN 值1 AND 值2,参数案例同上。
notBetween(R column, Object val1, Object val2)
notBetween(boolean condition, R column, Object val1, Object val2)
like
LIKE '%值%',参数同上。
like(R column, Object val)
like(boolean condition, R column, Object val)
案例演示:
@Test
public void likeTest02() {
System.out.println("----- like ------");
LambdaQueryWrapper<OrderTbl> queryWrapper = Wrappers.lambdaQuery();
queryWrapper.like(OrderTbl::getUserId,123); // AND (user_id LIKE '%123%')
//queryWrapper.like(true,OrderTbl::getUserId,123);
List<OrderTbl> list = orderTblService.list(queryWrapper);
}
notLike
NOT LIKE '%值%',参数案例同上。
notLike(R column, Object val)
notLike(boolean condition, R column, Object val)
likeLeft
LIKE '%值',参数案例同上。
likeLeft(R column, Object val)
likeLeft(boolean condition, R column, Object val)
likeRight
LIKE '值%',参数案例同上。
likeRight(R column, Object val)
likeRight(boolean condition, R column, Object val)
isNull
字段 IS NULL
isNull(R column)
isNull(boolean condition, R column)
参数说明:
column: 字段
condition : 该条件是否加入最后生成的sql中
案例演示:
@Test
public void isNullTest02() {
System.out.println("----- isNull ------");
LambdaQueryWrapper<OrderTbl> queryWrapper = Wrappers.lambdaQuery();
queryWrapper.isNull(OrderTbl::getGmtCreate); // AND (gmt_create IS NULL)
//queryWrapper.isNull(true, OrderTbl::getGmtCreate);
List<OrderTbl> list = orderTblService.list(queryWrapper);
}
isNotNull
字段 IS NOT NULL,参数案例同上。
isNotNull(R column)
isNotNull(boolean condition, R column)
in
字段 IN (value.get(0), value.get(1), ...)
in(R column, Collection<?> value)
in(boolean condition, R column, Collection<?> value)
案例演示:
@Test
public void inTest02() {
System.out.println("----- in ------");
LambdaQueryWrapper<OrderTbl> queryWrapper = Wrappers.lambdaQuery();
List<Long> userIdList=new ArrayList<>();
userIdList.add(123L);
userIdList.add(456L);
queryWrapper.in(OrderTbl::getUserId,userIdList); // AND (user_id IN (123,456))
List<OrderTbl> list = orderTblService.list(queryWrapper);
}
}
notIn
字段 NOT IN (value.get(0), value.get(1), ...),参数案例同上
notIn(R column, Collection<?> value)
notIn(boolean condition, R column, Collection<?> value)
notIn(R column, Object... values)
notIn(boolean condition, R column, Object... values)
inSql
字段 IN ( sql语句 ),子查询
inSql(R column, String inValue)
inSql(boolean condition, R column, String inValue)
案例演示:
@Test
public void inSqlTest02() {
System.out.println("----- in ------");
LambdaQueryWrapper<OrderTbl> queryWrapper = Wrappers.lambdaQuery();
queryWrapper.inSql(OrderTbl::getUserId,"Select user_id From order_tbl"); // AND (user_id IN (Select user_id From order_tbl))
List<OrderTbl> list = orderTblService.list(queryWrapper);
}
notInSql
字段 NOT IN ( sql语句 ),参数案例同上
notInSql(R column, String inValue)
notInSql(boolean condition, R column, String inValue)
groupBy
groupBy(R... columns)
groupBy(boolean condition, R... columns)
分组:GROUP BY 字段, ...
orderByAsc
排序:ORDER BY 字段, ... ASC
orderByAsc(R... columns)
orderByAsc(boolean condition, R... columns)
orderByDesc
排序:ORDER BY 字段, ... DESC
orderByDesc(R... columns)
orderByDesc(boolean condition, R... columns)
orderBy
排序:ORDER BY 字段, ...
orderBy(boolean condition, boolean isAsc, R... columns)
having
HAVING ( sql语句 )
having(String sqlHaving, Object... params)
having(boolean condition, String sqlHaving, Object... params)
func
func 方法(主要方便在出现if...else下调用不同方法能不断链), 使用函数式Consumer 接口生产数据,可以用if...else对Wrapper进行构建。
func(Consumer<Children> consumer)
func(boolean condition, Consumer<Children> consumer)
案例演示:
@Test
public void funcTest02() {
System.out.println("----- in ------");
LambdaQueryWrapper<OrderTbl> queryWrapper = Wrappers.lambdaQuery();
queryWrapper.func((i) -> {
if (true){
i.eq(OrderTbl::getUserId,"123"); // AND (user_id = '123')
}else {
i.ne(OrderTbl::getUserId,"123");
}
});
List<OrderTbl> list = orderTblService.list(queryWrapper);
}
}
or
拼接 OR,主动调用or表示紧接着下一个方法不是用and连接!(不调用or则默认为使用and连接)
or()
or(boolean condition)
OR 嵌套
or(Consumer<Param> consumer)
or(boolean condition, Consumer<Param> consumer)
案例演示 :
需要注意写法
@Test
public void orTest02() {
System.out.println("----- or ------");
LambdaQueryWrapper<OrderTbl> queryWrapper = Wrappers.lambdaQuery();
//queryWrapper.eq(OrderTbl::getMoney, 1000).or().eq(OrderTbl::getCommodityCode, "Phone"); // AND (money = 1000 OR commodity_code = 'Phone')
queryWrapper.eq(OrderTbl::getMoney, 1000).or((i) -> {
i.eq(OrderTbl::getUserId, 123);
});
List<OrderTbl> list = orderTblService.list(queryWrapper);
}
and
AND 嵌套
and(Consumer<Param> consumer)
and(boolean condition, Consumer<Param> consumer)
nested
正常嵌套 不带 AND 或者 OR
nested(Consumer<Param> consumer)
nested(boolean condition, Consumer<Param> consumer)
案例演示:
@Test
public void nestedTest02() {
System.out.println("----- nested ------");
LambdaQueryWrapper<OrderTbl> queryWrapper = Wrappers.lambdaQuery();
// AND ((commodity_code = 'Iphone' AND count <> 0))
queryWrapper.nested(i -> {
i.eq(OrderTbl::getCommodityCode, "Iphone").ne(OrderTbl::getCount, 000);
});
List<OrderTbl> list = orderTblService.list(queryWrapper);
}
apply
拼接 sql,该方法可用于数据库函数 动态入参的params对应前面applySql内部的{index}部分.这样是不会有sql注入风险的,反之会有!
apply(String applySql, Object... params)
apply(boolean condition, String applySql, Object... params)
last
无视优化规则直接拼接到 sql 的最后,只能调用一次,多次调用以最后一次为准 有sql注入的风险,请谨慎使用。
last(String lastSql)
last(boolean condition, String lastSql)
exists
拼接 EXISTS ( sql语句 )。
exists(String existsSql)
exists(boolean condition, String existsSql)
notExists
拼接 NOT EXISTS ( sql语句 )
notExists(String notExistsSql)
notExists(boolean condition, String notExistsSql)
QueryWrapper
继承自 AbstractWrapper ,自身的内部属性 entity 也用于生成 where 条件及 LambdaQueryWrapper, 可以通过 new QueryWrapper().lambda() 方法获取。
select
设置查询字段,方法分为两类,第二类方法为:过滤查询字段(主键除外),入参不包含 class 的调用前需要wrapper内的entity属性有值! 这两类方法重复调用以最后一次为准
select(String... sqlSelect)
select(Predicate<TableFieldInfo> predicate)
select(Class<T> entityClass, Predicate<TableFieldInfo> predicate)
案例演示:
@Test
public void selectTest02() {
System.out.println("----- select ------");
LambdaQueryWrapper<OrderTbl> queryWrapper = Wrappers.lambdaQuery();
// SELECT dept_id,commodity_code FROM order_tbl WHERE is_deleted=0
//queryWrapper.select(OrderTbl::getDeptId,OrderTbl::getCommodityCode);
// SELECT id,user_id FROM order_tbl WHERE is_deleted=0
queryWrapper.select(OrderTbl.class, i -> {
return i.getProperty().startsWith("user");
});
List<OrderTbl> list = orderTblService.list(queryWrapper);
}
UpdateWrapper
继承自 AbstractWrapper ,自身的内部属性 entity 也用于生成 where 条件及 LambdaUpdateWrapper, 可以通过 new UpdateWrapper().lambda() 方法获取!
set
SQL SET 字段
set(String column, Object val)
set(boolean condition, String column, Object val)
setSql
设置 SET 部分 SQL
setSql(String sql)
使用 Wrapper 自定义SQL
注意事项: 需要mybatis-plus版本 >= 3.0.7 param 参数名要么叫ew,要么加上注解@Param(Constants.WRAPPER) 使用${ew.customSqlSegment} 不支持 Wrapper 内的entity生成where语句。
案例演示:
- Mapper添加方法
@Select("select * from order_tbl ${ew.customSqlSegment}")
List<OrderTbl> getAll(@Param(Constants.WRAPPER) Wrapper wrapper);
- 调用
@Test
public void wrapperTest02() {
System.out.println("----- wrapper ------");
LambdaQueryWrapper<OrderTbl> queryWrapper = Wrappers.lambdaQuery();
queryWrapper.eq(OrderTbl::getCommodityCode,"phone");
orderTblMapper.getAll(queryWrapper); // WHERE is_deleted=0 AND (commodity_code = 'phone')
List<OrderTbl> list = orderTblService.list(queryWrapper);
}
链式调用 lambda 式
wrapper支持链式调用
// 区分:
// 链式调用 普通
UpdateChainWrapper<T> update();
// 链式调用 lambda 式。注意:不支持 Kotlin
LambdaUpdateChainWrapper<T> lambdaUpdate();
// 等价示例:
query().eq("id", value).one();
lambdaQuery().eq(Entity::getId, value).one();
// 等价示例:
update().eq("id", value).remove();
lambdaUpdate().eq(Entity::getId, value).remove();
参考: https://baomidou.com/
来源:https://yunyanchengyu.blog.csdn.net/article/details/115905137