Lambda表达式优化MyBatis动态参数包装器,实现字段名类型安全、条件解耦复用、空值安全更新及SQL注入防护。

用Lambda表达式优化MyBatis动态参数包装器,核心是把字段名从字符串硬编码升级为编译期可校验的类型安全引用,同时让条件组装逻辑更清晰、更易维护。关键不在于写得“炫”,而在于让条件判断和字段操作真正解耦、可复用、不易出错。
用LambdaQueryWrapper替代字符串拼接查询条件
传统方式中,每个if判断都要手动写字段名字符串,容易漏判、错判或前后不一致。LambdaQueryWrapper通过方法引用来绑定实体属性,编译器自动检查是否存在该Getter,重构时也能联动更新。
- 直接使用User::getUsername代替"username",拼错会立即报红
- 组合多个条件时语义自然:.eq(User::getStatus, 1).like(User::getPhone, "138%").between(User::getCreateTime, start, end)
- 模糊匹配推荐用likeRight()(前缀匹配)或likeLeft()(后缀匹配),比like()更高效且避免全表扫描
用LambdaUpdateChainWrapper实现选择性字段更新
业务中常需“只改某几个字段”,而不是加载整个对象再全量更新。LambdaUpdateChainWrapper支持链式set,并天然规避空值误更新问题。
- 调用lambdaUpdate()获取实例,无需传参,结尾直接update()
- 只更新非空字段:.set(User::getNickname, user.getNickname()).set(User::getEmail, user.getEmail()).eq(User::getId, id)
- 避免null覆盖数据库原值:可在set前加判空逻辑,或配合setIfPresent()方法(部分版本支持)
用setSql处理无法用set()表达的动态计算场景
当需要数据库端执行运算(如积分累加、库存扣减、JSON字段更新)时,常规set()无法满足。setSql允许插入原生SQL片段,但必须严格防范注入。
- 安全写法:.setSql("points = points + 100").setSql("version = version + 1").eq(User::getId, userId)
- 涉及用户输入时,绝不可拼接变量到setSql中;应改用参数化set()配合数据库函数,或提前校验/转义
- MySQL空间字段更新示例:.setSql("location = POINT(?, ?)", lon, lat),注意此处仍走预编译参数传递
封装通用条件构建工具类,避免重复判空逻辑
当查询参数来自DTO或前端请求体时,大量if (obj.getXxx() != null) {...} 易冗余且易漏。可封装静态工具方法统一处理。
- 定义MyBatisHelper.equals()接收Function,自动跳过null或空字符串
- 调用方式:equals(query.getCityCode(), w -> w.eq(User::getCityCode, query.getCityCode()))
- 支持like、in、gt等多种条件类型,内部统一判空逻辑,上层代码专注业务意图










