Mybatis Plus Wrapper 条件构造器(超详细)

更新时间 2023-01-04 15:42:50

一则或许对你有用的小广告

欢迎加入小哈的星球 ,你将获得:专属的项目实战 / Java 学习路线 / 一对一提问 / 学习打卡 / 赠书活动

目前, 星球 内第一个项目:全栈前后端分离博客项目,演示地址:http://116.62.199.48/, 1.0 版本已经更新完毕,正在更新 2.0 版本。采用技术栈 Spring Boot + Mybatis Plus + Vue 3.x + Vite 4手把手,前端 + 后端全栈开发,从 0 到 1 讲解每个功能点开发步骤,1v1 答疑,陪伴式直到项目上线,目前已更新了 224 小节,累计 35w+ 字,讲解图:1544 张,还在持续爆肝中,后续还会上新更多项目,目标是将 Java 领域典型的项目都整上,如秒杀系统、在线商城、IM 即时通讯、权限管理等等,已有 1000+ 小伙伴加入,欢迎点击围观

什么是条件构造器?

在 Mybatis 中,我们查询或者更新指定数据,可以直接在 xml 文件中写 SQL,然后通过占位符传入条件参数即可,比如你想根据用户 ID 去更新某个用户数据,那么 SQL 条件大致为 where id = #{id}

而在 Mybatis Plus 中,我们都知道 Mybatis Plus 大部分情况下无需像 Mybatis 那样编写繁琐的 xml 文件,仅需简单的几行代码即可完成数据库操作。那么,条件要怎么设定呢?

轮到今天的主角出场了!在 Mybatis Plus 中,利用条件构造器 Wrapper 可以帮助我们组装各种 where 条件,具体实现类如 QueryWrapperUpdateWrapper 等,在查询、更新、删除操作中会被频繁用到。

Wrapper 继承关系

Wrapper 是个抽象类,先看下它的继承关系图:

Mybatis Plus Wrapper 继承关系Mybatis Plus Wrapper 继承关系

解释一下各个子类的作用:

Wrapper  条件构造抽象类
    -- AbstractWrapper 查询条件封装,用于生成 sql 中的 where 语句。
        -- QueryWrapper Entity 条件封装操作类,用于查询。
        -- UpdateWrapper Update 条件封装操作类,用于更新。
        -- AbstractLambdaWrapper 使用 Lambda 表达式封装 wrapper
            -- LambdaQueryWrapper 使用 Lambda 语法封装条件,用于查询。
            -- LambdaUpdateWrapper 使用 Lambda 语法封装条件,用于更新。
    -- AbstractChainWrapper 链式查询条件封装 
    	-- UpdateChainWrapper 链式条件封装操作类,用于更新。
    	-- LambdaQueryChainWrapper 使用 Lambda 语法封装条件,支持链式调用,用于查询
    	-- LambdaUpdateChainWrapper 使用 Lambda 语法封装条件,支持链式调用,用于更新
    	-- QueryChainWrapper 链式条件封装操作类,用于查询。

TIP : Kt 开头的类是使用 Kotlin 语言编写,咱是 Java,不用管。

AbstractWrapper

QueryWrapper (LambdaQueryWrapper) 和 UpdateWrapper (LambdaUpdateWrapper) 的父类 用于生成 sql 的 where 条件, entity 属性也用于生成 sql 的 where 条件

allEq :多字段等于查询

全部自动等于判断,或者个别自动非空判断:

// params : key 为数据库字段名, value 为字段值
allEq(Map<R, V> params)
// null2IsNull : 为 true 则在 map 的 value 为 null 时调用 isNull 方法,为 false 时则忽略 value 为null的
allEq(Map<R, V> params, boolean null2IsNull)
allEq(boolean condition, Map<R, V> params, boolean null2IsNull)
  • 代码示例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 : 过滤函数,是否允许字段传入比对条件中
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) 
  • 代码示例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 = '老王', 具体示例代码点这里

eq :单字段等于

eq(R column, Object val)
eq(boolean condition, R column, Object val)
  • 代码示例: eq("name", "老王")相当于条件name = '老王', 具体代码示例点这里

ne :不等于

ne(R column, Object val)
ne(boolean condition, R column, Object val)
  • 代码示例:ne("name", "老王")相当于条件name <> '老王', 具体代码示例点这里

gt : 大于

gt(R column, Object val)
gt(boolean condition, R column, Object val)
  • 代码示例: ge("age", 18)相当于条件age >= 18, 具体代码示例点这里

ge:大于等于

ge(R column, Object val)
ge(boolean condition, R column, Object val)
  • 例: ge("age", 18)相当于条件age >= 18, 具体代码示例点这里

lt:小于

lt(R column, Object val)
lt(boolean condition, R column, Object val)
  • 例: lt("age", 18)相当于条件age < 18, 具体代码示例点这里

le : 小于等于

le(R column, Object val)
le(boolean condition, R column, Object val)
  • 例: le("age", 18)相当于条件age <= 18, 具体代码示例点这里

between

between(R column, Object val1, Object val2)
between(boolean condition, R column, Object val1, Object val2)

作用:BETWEEN 值1 AND 值2

  • 例: between("age", 18, 30)相当于条件age between 18 and 30, 具体示例代码点这里

notBetween

notBetween(R column, Object val1, Object val2)
notBetween(boolean condition, R column, Object val1, Object val2)

作用:NOT BETWEEN 值1 AND 值2

  • 例: notBetween("age", 18, 30)相当于条件age not between 18 and 30, 具体示例代码点这里

like : 模糊查询

like(R column, Object val)
like(boolean condition, R column, Object val)

作用:LIKE '%值%'

  • 例: like("name", "王")相当于条件name like '%王%', 具体示例代码点这里

notLike

notLike(R column, Object val)
notLike(boolean condition, R column, Object val)

作用:NOT LIKE '%值%'

  • 例: notLike("name", "王")相当于条件name not like '%王%', 具体示例代码点这里

likeLeft

likeLeft(R column, Object val)
likeLeft(boolean condition, R column, Object val)

作用:LIKE '%值'

例: likeLeft("name", "王")相当于条件name like '%王, 具体示例代码点这里

likeRight

likeRight(R column, Object val)
likeRight(boolean condition, R column, Object val)

作用: LIKE '值%'

例: likeRight("name", "王")相当于条件name like '王%, 具体示例代码点这里

isNull :为空

isNull(R column)
isNull(boolean condition, R column)

作用:字段 IS NULL

  • 例: isNull("name")相当于条件name is null, 具体示例代码点这里

isNotNull : 非空

isNotNull(R column)
isNotNull(boolean condition, R column)

作用: 字段 IS NOT NULL

  • 例: isNotNull("name")相当于条件name is not null, 具体示例代码点这里

in

in(R column, Collection<?> value)
in(boolean condition, R column, Collection<?> value)

说明:字段 IN (value.get(0), value.get(1), ...)

  • 例: in("age",{1,2,3})相当于条件age in (1,2,3),具体示例代码点这里
in(R column, Object... values)
in(boolean condition, R column, Object... values)

说明:字段 IN (v0, v1, ...)

  • 例: in("age", 1, 2, 3) 相当于条件age in (1,2,3),具体示例代码点这里

notIn

notIn(R column, Collection<?> value)
notIn(boolean condition, R column, Collection<?> value)

作用:NOT IN (value.get(0), value.get(1), ...)

  • 例: notIn("age",{1,2,3})相当于条件age not in (1,2,3), 具体示例代码点这里

inSql :子查询

inSql(R column, String inValue)
inSql(boolean condition, R column, String inValue)

作用:字段 IN ( sql语句 )

  • 例: inSql("age", "1,2,3,4,5,6")相当于条件age in (1,2,3,4,5,6), 具体代码示例点这里
  • 例: inSql("id", "select id from table where id < 3")相当于条件id in (select id from table where id < 3), 具体代码示例点这里 ;

notInSql

notInSql(R column, String inValue)
notInSql(boolean condition, R column, String inValue)

作用:NOT IN ( sql语句 )

  • 例: notInSql("age", "1,2,3,4,5,6")相当于条件age not in (1,2,3,4,5,6), 具体代码示例点这里
  • 例: notInSql("id", "select id from table where id < 3")相当于条件id not in (select id from table where id < 3), 具体代码示例点这里

groupBy:分组

groupBy(R... columns)
groupBy(boolean condition, R... columns)

说明:分组 GROUP BY 字段。

  • 例: groupBy("id", "name")相当于条件group by id,name, 具体示例代码点这里

orderByAsc:升序

orderByAsc(R... columns)
orderByAsc(boolean condition, R... columns)

说明:升序排序:ORDER BY 字段, ... ASC

  • 例: orderByAsc("id", "name")相当于条件order by id ASC,name ASC, 具体代码示例点这里

orderByDesc:降序

orderByDesc(R... columns)
orderByDesc(boolean condition, R... columns)

说明:降序排序:ORDER BY 字段, ... DESC

  • 例: orderByDesc("id", "name")相当于条件order by id DESC,name DESC, 具体代码示例点这里

orderBy : 排序

orderBy(boolean condition, boolean isAsc, R... columns)

说明:排序:ORDER BY 字段, ...

  • 例: orderBy(true, true, "id", "name")相当于条件order by id ASC,name ASC, 具体示例代码点这里

having

作用:HAVING ( sql语句 )

having(String sqlHaving, Object... params)
having(boolean condition, String sqlHaving, Object... params)
  • 例: having("sum(age) > 10")相当于条件having sum(age) > 10
  • 例: having("sum(age) > {0}", 11)相当于条件having sum(age) > 11

func

作用:func 方法主要方便在出现if...else下调用不同方法能不断链

func(Consumer<Children> consumer)
func(boolean condition, Consumer<Children> consumer)
  • 例: func(i -> if(true) {i.eq("id", 1)} else {i.ne("id", 1)})

or

拼接 or :

or()
or(boolean condition)
  • 例: eq("id",1).or().eq("name","老王")相当于条件id = 1 or name = '老王', 具体示例代码点这里

or 嵌套:

  • 例: or(i -> i.eq("name", "李白").ne("status", "活着"))相当于条件or (name = '李白' and status <> '活着'), 具体示例代码点这里

and 嵌套

and(Consumer<Param> consumer)
and(boolean condition, Consumer<Param> consumer)

作用:AND 嵌套

  • 例: and(i -> i.eq("name", "李白").ne("status", "活着"))相当于条件and (name = '李白' and status <> '活着'), 具体示例代码点这里

nested

作用:正常嵌套 不带 AND 或者 OR

nested(Consumer<Param> consumer)
nested(boolean condition, Consumer<Param> consumer)
  • 例: nested(i -> i.eq("name", "李白").ne("status", "活着"))相当于条件(name = '李白' and status <> '活着')

apply

作用:拼接 sql

注意:该方法可用于数据库函数 动态入参的params对应前面applySql内部的{index}部分.这样是不会有sql注入风险的,反之会有!

apply(String applySql, Object... params)
apply(boolean condition, String applySql, Object... params)
  • 例: 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 的最后。

注意:只能调用一次,多次调用以最后一次为准 有sql注入的风险,请谨慎使用。

last(String lastSql)
last(boolean condition, String lastSql)
  • 例: last("limit 1"), 具体代码示例点这里

exists

exists(String existsSql)
exists(boolean condition, String existsSql)

作用:拼接 EXISTS ( sql语句 )

  • 例: exists("select id from table where age = 1")相当于条件exists (select id from table where age = 1), 具体示例代码点这里

notExists

notExists(String notExistsSql)
notExists(boolean condition, String notExistsSql)

作用:拼接 NOT EXISTS ( sql语句 )

  • 例: notExists("select id from table where age = 1")相当于条件not exists (select id from table where age = 1), 具体示例代码点这里

QueryWrapper

QueryWrapper 继承自 AbstractWrapper ,自身的内部属性 entity 也用于生成 where 条件。LambdaQueryWrapper 支持以 lambda 形式组装条件, 可以通过 new QueryWrapper().lambda() 方法获取实例。

select

作用:设置查询字段

select(String... sqlSelect)
select(Predicate<TableFieldInfo> predicate)
select(Class<T> entityClass, Predicate<TableFieldInfo> predicate)

TIP :

以上方法分为两类. 第二类方法为:过滤查询字段(主键除外),入参不包含 class 的调用前需要wrapper内的entity属性有值! 这两类方法重复调用以最后一次为准

  • 例: select("id", "name", "age")
  • 例: select(i -> i.getProperty().startsWith("test"))

UpdateWrapper

UpdateWrapper 继承自 AbstractWrapper ,自身的内部属性 entity 也用于生成 where 条件。LambdaUpdateWrapper 支持以 lambda 形式组装条件, 可以通过 new QueryWrapper().lambda() 方法获取实例。

set

作用:SET 字段

set(String column, Object val)
set(boolean condition, String column, Object val)
  • 例: set("name", "老李头")
  • 例: set("name", "")--->数据库字段值变为空字符串
  • 例: set("name", null)--->数据库字段值变为null

setSql

作用:设置 SET 部分 SQL

setSql(String sql)
  • 例: setSql("name = '老李头'")

lambda

作用:用于获取 LambdaWrapper

  • QueryWrapper中是获取LambdaQueryWrapper
  • UpdateWrapper中是获取LambdaUpdateWrapper.