跳到主要内容

14、Mybatis-Plus入门 - 条件构造器

前言

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

NOTBETWEEN 值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

NOTLIKE ‘%值%’,参数案例同上。

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

SQLSET 字段

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语句。

案例演示

1、 Mapper添加方法;

    @Select("select * from order_tbl ${ew.customSqlSegment}")
    List<OrderTbl> getAll(@Param(Constants.WRAPPER) Wrapper wrapper);

1、 调用;

    @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/