Java多条件筛选应使用MyBatis-Plus的QueryWrapper实现动态查询,自动忽略空值,避免SQL注入;需封装ConditionBuilder解耦逻辑,建立联合索引优化性能。

Java中实现多条件筛选,核心在于构建灵活、可扩展的动态查询逻辑,避免硬编码SQL或大量if-else拼接。关键不是写死条件,而是让查询条件“可插拔”——用户选了哪些字段、填了哪些值,系统就自动加入对应WHERE子句。
用QueryWrapper(MyBatis-Plus)简化动态条件组装
MyBatis-Plus的QueryWrapper天然支持链式调用和空值跳过,是实现多条件筛选最常用且简洁的方式。它会自动忽略值为null、空字符串或集合为空的条件。
- 对字符串字段:用like、eq、ne等方法,传入参数前无需手动判空
- 对数值/日期字段:直接传参,若前端未提交该字段(即后端接收为null),对应条件不会进入SQL
- 示例:用户输入用户名关键词+选择状态+指定创建时间范围,代码只需:
QueryWrapper
wrapper.like(StringUtils.isNotBlank(username), "username", username)
.eq(status != null, "status", status)
.between(startTime != null && endTime != null, "create_time", startTime, endTime);
封装通用条件处理器,解耦业务与查询逻辑
当筛选字段较多(如10+个)、规则较复杂(模糊+精确+范围+IN多选)时,建议将条件解析提取为独立组件,比如ConditionBuilder类。它接收DTO对象,按约定规则转换为QueryWrapper或Criteria对象。
立即学习“Java免费学习笔记(深入)”;
- 统一处理“空字符串视为忽略”、“-1表示全部”、“字符串trim后再判断”等细节
- 支持自定义条件映射,例如DTO中userTypeList字段自动转为IN子句
- 便于单元测试和后期新增筛选项,不侵入Service主流程
避免SQL注入与类型安全:别用字符串拼接,慎用apply()
绝对不要用wrapper.apply("age > " + age)这类方式拼接用户输入——存在SQL注入风险。所有用户输入必须走参数化占位符(?)。
- 优先使用内置方法:gt("age", age)、in("type", types)
- 必须用apply()时,只用于固定SQL片段(如函数、排序伪列),且参数仍需用{}占位并传参
- 对枚举/状态码等受限值,入库前做白名单校验,防止恶意传入非法字符串
分页与性能兼顾:合理使用索引与延迟加载
多条件组合容易导致全表扫描。即使功能跑通,也要关注实际执行效率。










