lambda表达式优化mybatis动态sql的核心是用类型安全的方法引用替代字符串字段名,并自动过滤空值。支持eq/like/in等所有条件,通过布尔开关或工具方法统一判空,结合predicate收集复杂条件,再用setsql实现动态字段更新。

用 Lambda 表达式优化 MyBatis 动态 SQL 的参数预处理,核心是把“字段名硬编码 + 手动判空”升级为“类型安全引用 + 条件自动过滤”。它不改变 SQL 执行逻辑,而是让 Java 层组装条件的过程更健壮、可读、易维护。
避免字符串字段名,用方法引用来保障类型安全
传统 QueryWrapper 中写 wrapper.eq("user_name", name),字段名是字符串,一旦实体类改名或拼错,编译不报错,运行才出问题。换成 LambdaQueryWrapper 后:
-
wrapper.eq(User::getUserName, name)—— 编译器直接校验getUserName()是否存在、返回类型是否匹配 - IDE 自动补全字段,重构时所有引用同步更新,不会漏掉某处的字符串
- 适用于
like、in、between等所有条件方法,统一风格
自动跳过空值,省去大量 if 判空代码
原来要这样写:
if (StringUtils.isNotBlank(name)) wrapper.like("name", name);
if (status != null) wrapper.eq("status", status);
if (CollectionUtils.isNotEmpty(ids)) wrapper.in("id", ids);
用 LambdaQueryWrapper 配合工具方法(如自定义 MyBatisHelper)或直接链式调用,可让空值自动失效:
-
wrapper.like(StringUtils.isNotBlank(name), User::getUserName, name)—— 第一个参数为布尔开关,true 才执行 - 或封装通用方法:
MyBatisHelper.likes(name, u -> wrapper.like(User::getUserName, u)),内部自动判空 - 对集合、数字、日期等类型,
checkEmpty()工具方法统一识别 null / 空字符串 / 空集合,避免重复逻辑
组合复杂条件时,用谓词收集+批量应用提升可读性
当多个字段支持“任意一个匹配即查中”(OR 语义),或需要分组嵌套(如 `(name like ? OR email like ?) AND status = ?`),直接链式调用易混乱。推荐分离条件收集与应用:
- 先用
List<pre class="brush:php;toolbar:false;" dicate>></pre>收集业务规则:predicates.add(u -> u.getName().contains(kw)); predicates.add(u -> u.getEmail().contains(kw)); - 再统一注入 wrapper:
predicates.forEach(wrapper::or)或用.and(i -> i.or(...).or(...))分组 - 好处是:条件来源清晰、可单元测试、新增维度只需加一行 predicate,不碰 SQL 组装逻辑
配合 setSql 实现动态字段更新,避免 if-else 分支爆炸
更新操作中常需“按参数类型决定更新哪个字段”,传统做法是多个 if-else 调不同 Mapper 方法。用 LambdaUpdateChainWrapper + setSql 可一行收口:
-
.setSql(type == 1, "score = score + #{value}")—— 条件为 true 才拼入该 SQL 片段 -
.setSql(type == 2, "level = CASE WHEN score > 100 THEN 'A' ELSE 'B' END")—— 支持复杂表达式和数据库函数 - 注意:SQL 片段中用
#{value}安全传参,禁用${}拼接,防注入










