源本科技 | 码上会

Chain 链式编程

2026/04/02
3
0

引言

MyBatis-Plus Chain 链式编程是官方提供的极简数据库操作 API,基于构造器模式 + 流式调用设计,让单表 CRUD 代码一行写完、无需创建 QueryWrapper 对象,代码更简洁、可读性更强。

Chain 分为两大核心类型:

  • QueryChain:查询专用(list、one、count、page)

  • UpdateChain:更新 / 删除专用(update、remove)

每种类型又提供普通版Lambda 版Lambda 版是企业开发首选(防硬编码、编译期检查)。


核心定义

类型

普通链式

Lambda 链式

核心优势

查询

QueryChainWrapper

LambdaQueryChainWrapper

类型安全、无字符串硬编码

更新

UpdateChainWrapper

LambdaUpdateChainWrapper

编译期校验字段、重构安全

基础接口

// 1. 查询链式
QueryChainWrapper<T> query();                // 普通版(字段用字符串)
LambdaQueryChainWrapper<T> lambdaQuery();    // Lambda 版(推荐)

// 2. 更新链式
UpdateChainWrapper<T> update();              // 普通版
LambdaUpdateChainWrapper<T> lambdaUpdate();  // Lambda 版(推荐)

关键说明

  1. Chain 必须基于 BaseMapper 使用(Service 层 / Mapper 层均可直接调用)

  2. Lambda 链式不支持 Kotlin(Kotlin 请用普通链式)

  3. 无需手动 new Wrapper,链式调用自动构建条件

  4. 最后调用执行方法(list/one/update/remove 等)


前置准备

可直接使用的环境

Chain 是 MyBatis-Plus 自带功能,无需额外配置,只需满足:

  • 依赖:mybatis-plus-boot-starter 3.5.x+

  • Mapper 继承 BaseMapper<T>

  • Service 可继承 ServiceImpl<M,T>(直接调用 chain 方法)


QueryChain 查询链式

LambdaQueryChain

企业首选

优势:使用 类::方法 引用字段,无魔法值、编译检查、重构安全

常用查询方法

  • list():返回集合

  • one():返回单条(必须确保唯一)

  • count():返回总数

  • page():分页查询

  • exists():是否存在

// 1. 查询姓名=张三,年龄>18 的用户列表
List<User> userList = userService.lambdaQuery()
        .eq(User::getUsername, "张三")
        .gt(User::getAge, 18)
        .orderByDesc(User::getCreateTime)
        .list();

// 2. 根据 ID 查询单条
User user = userService.lambdaQuery()
        .eq(User::getId, 1L)
        .one();

// 3. 查询数量
Long count = userService.lambdaQuery()
        .like(User::getEmail, "@qq.com")
        .count();

// 4. 条件判断链式(动态条件)
List<User> userList = userService.lambdaQuery()
        .eq(StringUtils.hasText(name), User::getUsername, name)
        .gt(age != null, User::getAge, age)
        .list();

// 5. 查询指定字段(只查 id、username)
List<User> userList = userService.lambdaQuery()
        .select(User::getId, User::getUsername)
        .eq(User::getAge, 20)
        .list();

普通 QueryChain

字符串字段名

适合 Kotlin / 简单场景

List<User> list = userService.query()
        .eq("username", "张三")
        .between("age", 18, 30)
        .list();

UpdateChain 更新链式

LambdaUpdateChain

支持条件构造 + set 赋值 + 执行更新 / 删除,一行完成。

核心方法

  • set(字段, 值):设置更新字段

  • setSql(...):SQL 表达式更新(如 set age = age + 1)

  • update():执行更新

  • remove():执行删除

// 1. 根据 ID 更新邮箱
boolean success = userService.lambdaUpdate()
        .eq(User::getId, 1L)
        .set(User::getEmail, "test@163.com")
        .update();

// 2. 年龄 +1(SQL 表达式)
userService.lambdaUpdate()
        .eq(User::getId, 1L)
        .setSql("age = age + 1")
        .update();

// 3. 多字段批量更新
userService.lambdaUpdate()
        .eq(User::getDeptId, 10L)
        .set(User::getStatus, 1)
        .set(User::getUpdateTime, LocalDateTime.now())
        .update();

// 4. 链式删除(条件删除)
userService.lambdaUpdate()
        .eq(User::getStatus, 0)
        .remove();

普通 UpdateChain

userService.update()
        .eq("id", 1L)
        .set("username", "张三")
        .update();

Service / Mapper 使用 Chain

Service

最常用

直接调用 lambdaQuery() / lambdaUpdate()

@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {

    public List<User> getList() {
        // 一行链式查询
        return lambdaQuery().eq(User::getStatus, 1).list();
    }
}

Mapper

直接调用

List<User> userList = userMapper.lambdaQuery()
        .eq(User::getAge, 25)
        .list();

最佳实践

动态条件

Chain 完美支持动态条件,无需 if / else 嵌套

lambdaQuery()
    .eq(StringUtils.hasText(name), User::getUsername, name)
    .gt(minAge != null, User::getAge, minAge)
    .lt(maxAge != null, User::getAge, maxAge)
    .list();

常用条件方法

eq()        // 等于
ne()        // 不等于
gt()        // 大于
ge()        // 大于等于
lt()        // 小于
le()        // 小于等于
like()      // 模糊匹配
likeRight() // 右模糊(索引生效)
between()   // 区间
orderByAsc()// 升序
orderByDesc()// 降序
isNull()    // 为空
isNotNull() // 非空
in()        // 包含

方法说明

方法

作用

list()

返回集合 List

one()

返回单个实体(唯一结果)

count()

返回总数 Long

page()

分页查询 IPage

update()

执行更新,返回 boolean

remove()

执行删除,返回 boolean

exists()

是否存在,返回 boolean


Chain vs 传统 Wrapper

方式

代码量

硬编码

编译检查

简洁度

传统 Wrapper

多(需 new 对象)

一般

Chain 链式

极少(一行完成)

无(Lambda)

极高

传统写法(对比)

QueryWrapper<User> wrapper = new QueryWrapper<>();
wrapper.eq("username", "张三");
wrapper.gt("age", 18);
List<User> list = userService.list(wrapper);

Chain 写法(简洁 50%+)

List<User> list = userService.lambdaQuery()
        .eq(User::getUsername, "张三")
        .gt(User::getAge, 18)
        .list();

常见问题

  1. one() 必须确保结果唯一 多条会抛异常,可用 oneOpt() 优雅空值处理。

  2. LambdaChain 不支持 Kotlin Kotlin 请使用普通链式 query() / update()

  3. 更新必须加条件 不加 eq 会更新全表,生产环境严禁使用。

  4. 链式顺序不影响结果 先条件后 set / 先 set 后条件均可,MP 自动解析。

  5. 性能与普通 Wrapper 完全一致 底层实现相同,仅语法糖优化,无性能损耗。


企业规范

  1. 统一使用 Lambda 链式(禁止字符串硬编码)

  2. 单表操作优先用 Chain,代码极简、维护成本低

  3. 动态条件必用链式布尔判断,避免 if 嵌套

  4. 更新 / 删除必须加 ID 或唯一条件

  5. 复杂多表查询不用 Chain,改用 XML / 注解 SQL


总结

  1. Chain = 流式链式 + 无 Wrapper 编程,是 MyBatis-Plus 最优雅的写法

  2. 两大类:lambdaQuery(查询)、lambdaUpdate(更新 / 删除)

  3. 核心优势:无硬编码、编译安全、代码精简、动态条件友好

  4. 使用姿势:条件构造 → 最后执行(list/one/update/remove)

  5. 企业标准:Lambda 链式 = 单表操作官方最佳实践