如何使用NamedParameterJdbcTemplate实现无IN子句的SELECT批量查询
基于NamedParameterJdbcTemplate的SELECT批量查询实现方案
你当前的循环单条查询方案在员工数量较多时,会产生大量数据库往返IO,性能损耗明显。我们可以通过动态拼接UNION ALL子句的方式,将多次查询合并为单次数据库请求,既不使用IN子句,也能大幅提升执行效率。
实现代码
命名参数版本(贴合你原有的使用习惯)
// 输入参数:List<Employee> employee List<String> finalProjectList; RowMapper<String> rowMapper = (rs, rowNum) -> rs.getString("project_name"); if (employee.isEmpty()) { finalProjectList = Collections.emptyList(); } else { StringBuilder sqlBuilder = new StringBuilder(); MapSqlParameterSource params = new MapSqlParameterSource(); for (int i = 0; i < employee.size(); i++) { if (i > 0) { sqlBuilder.append(" UNION ALL "); } // 每个员工的查询条件单独加后缀区分命名参数 sqlBuilder.append("SELECT project_name FROM employee WHERE id = :id_") .append(i) .append(" AND name = :name_") .append(i); Employee e = employee.get(i); params.addValue("id_" + i, e.getId()); params.addValue("name_" + i, e.getName()); } finalProjectList = namedParameterJdbcTemplate.query(sqlBuilder.toString(), params, rowMapper); }
占位符版本(更简洁)
// 输入参数:List<Employee> employee List<String> finalProjectList; RowMapper<String> rowMapper = (rs, rowNum) -> rs.getString("project_name"); if (employee.isEmpty()) { finalProjectList = Collections.emptyList(); } else { String singleQuery = "SELECT project_name FROM employee WHERE id = ? AND name = ?"; StringBuilder sqlBuilder = new StringBuilder(); List<Object> params = new ArrayList<>(); for (int i = 0; i < employee.size(); i++) { if (i > 0) { sqlBuilder.append(" UNION ALL "); } sqlBuilder.append(singleQuery); Employee e = employee.get(i); params.add(e.getId()); params.add(e.getName()); } finalProjectList = namedParameterJdbcTemplate.getJdbcOperations() .query(sqlBuilder.toString(), params.toArray(), rowMapper); }
方案说明
- 全程没有使用IN子句,完全符合要求
- 仅需1次数据库请求,相比循环查询性能提升非常明显,员工数量越多优势越大
- 保留了原查询的匹配逻辑,返回结果和你原有循环实现的结果完全一致
- 如果员工数量超过500,可以分批处理,每200个员工拼接一次UNION ALL,避免SQL过长导致的数据库解析异常
内容的提问来源于stack exchange,提问作者Prayas Bhatnagar
相关产品推荐
相关产品推荐

