preparedstatement动态条件过滤的核心是动态构建sql占位符与参数列表:用stringbuilder拼接where子句,arraylist存储参数,按?出现顺序严格设置参数,避免sql注入并保持预编译优势。

用 PreparedStatement 实现动态条件过滤,核心不是拼 SQL 字符串,而是动态构建参数占位符(?)和对应参数列表,再统一设置参数。关键在于避免 SQL 注入、保持预编译优势,同时让 WHERE 子句的条件数可变。
构建可变 WHERE 子句 + 动态参数列表
不硬编码固定数量的 ?,而是根据实际条件逐个追加条件片段和参数。用 StringBuilder 拼接 SQL 片段,用 ArrayList 存储参数值,最后遍历设置。
- 初始化基础 SQL(如
"SELECT * FROM user WHERE 1=1"),便于后续无脑用AND追加 - 每个非空/有效条件单独判断:若 name 不为空,追加
" AND name = ?"并把 name 加入参数列表 - 年龄范围、状态枚举、时间区间等同理,只在条件成立时才加入子句和参数
用 PreparedStatement 设置参数时按顺序严格对齐
PreparedStatement 的 setXxx(index, value) 中 index 从 1 开始,必须与 SQL 中 ? 出现的顺序完全一致。因此参数列表(如 List
Java开发手册规约集合,基于阿里巴巴Java开发手册(嵩山版)。 涵盖7大维度:编程规约、异常日志、单元测试、安全规约、MySQL数据库、工程结构、设计规约。 当用户需要:(1) 编写或审查Java代码 (2) 检查命名/代码规范 (3) 处理异常和日志 (4) 编写单元测试 (5) 安全编码 (6) 数据库设...
- 不要跳过某个
?或重用 index;动态条件意味着参数总数不确定,但顺序不能乱 - 示例:SQL 是
"WHERE 1=1 AND status = ? AND age > ?",则第 1 个参数设 status,第 2 个设 age,不可颠倒 - 建议封装一个工具方法:
setParameters(ps, params),循环调用ps.setObject(i+1, param)
处理 IN 查询、NULL 判断等特殊场景
IN 子句无法直接用单个 ? 代表多个值,需动态生成对应数量的 ?, ?, ?;而 IS NULL / IS NOT NULL 不能用 = ?,需单独写死条件。
- 对于
id IN (?, ?, ?):先根据集合大小生成"?," * (size-1) + "?",再拼进 SQL;参数列表直接 addAll(ids) - 对于可能为 null 的字段(如查询 “未分配部门”):用
"AND dept_id IS NULL"或"AND dept_id = ?"分支,不混用 - 避免
WHERE name = ? OR ? IS NULL这类写法——它破坏索引、语义不清,且参数重复传值易出错
完整轻量示例(含主键 ID、姓名、状态、年龄范围)
以下代码片段展示真实可用结构:
String sql = "SELECT * FROM user WHERE 1=1";
List<object> params = new ArrayList();
<p>if (userId != null) {
sql += " AND id = ?";
params.add(userId);
}
if (StringUtils.isNotBlank(name)) {
sql += " AND name LIKE ?";
params.add("%" + name + "%");
}
if (status != null) {
sql += " AND status = ?";
params.add(status);
}
if (minAge != null || maxAge != null) {
sql += " AND age BETWEEN ? AND ?";
params.add(minAge != null ? minAge : 0);
params.add(maxAge != null ? maxAge : 200);
}</p>
<p>try (Connection conn = dataSource.getConnection();
PreparedStatement ps = conn.prepareStatement(sql)) {</p>
<pre class="brush:java;toolbar:false;">for (int i = 0; i < params.size(); i++) {
ps.setObject(i + 1, params.get(i));
}
ResultSet rs = ps.executeQuery();
// 处理结果...
}
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










