动态sql多条件查询的核心是只拼接用户实际输入的有效条件,避免空值或默认值参与where过滤;常用mybatis的标签配合处理and逻辑,或用case when实现纯sql条件分支,同时需规范前端传参清洗与后端校验,并推荐使用querywrapper等构建器模式提升安全性与可维护性。

动态SQL多条件查询的核心是:只拼接用户实际输入的条件,避免空值或默认值参与WHERE过滤,防止查出错误数据或全表扫描。
用IF判断拼接条件(MyBatis示例)
MyBatis中常用
- 用户名不为空才加
AND user_name LIKE CONCAT('%', #{userName}, '%') - 状态为有效值(如0/1)才加
AND status = #{status},避免传入null或-1时误匹配 - 时间范围需同时校验开始和结束时间,仅一个有值时按单边查询处理
用CASE WHEN做条件分支(纯SQL写法)
在存储过程或视图中,可用CASE WHEN配合参数做逻辑路由。例如:
SELECT * FROM order WHERE
status = CASE WHEN #{status} IS NOT NULL THEN #{status} ELSE status END
AND (#{startTime} IS NULL OR create_time >= #{startTime})
AND (#{endTime} IS NULL OR create_time
这种写法不拼SQL,但需注意:数据库仍可能因参数为NULL跳过索引,建议配合函数索引或改用动态拼接。
1 系统使用三层构架2 数据库访问使用sqlHelper3 编辑器使用FreeTextBox4 布局采用Div+Css5 正则表达式实现数据验证6 动态构建sql查询语句
避免常见坑:空字符串、0、NULL混用
前端传参常把未填项发成空字符串""或数字0,后端要提前清洗:
- 字符串类型:trim后判空,""和" "(中文空格)都应视为无效
- 数值类型:0可能是合法值(如“未评分”),需约定特殊标记(如-999)表示“不筛选”
- 日期类型:不能直接用
#{date} != null,Java里String转Date失败会抛异常,应先校验格式再传参
用构建器模式封装(Java推荐)
用QueryWrapper(MyBatis-Plus)或自定义CriteriaBuilder,让代码可读性更强:
QueryWrapper
if (StringUtils.isNotBlank(req.getName())) {
wrapper.like("user_name", req.getName());
}
if (req.getStatus() != null && req.getStatus() >= 0) {
wrapper.eq("status", req.getStatus());
}
userMapper.selectList(wrapper);
这种方式天然规避SQL注入,逻辑清晰,扩展新增条件只需加一行if。









