Spring JdbcTemplate中SELECT查询IN子句数组参数绑定问题
问题原因
基础JdbcTemplate不支持直接给单个?占位符传入集合/数组作为IN子句参数,框架会将整个集合识别为单个参数值,不会自动展开为多个逗号分隔的占位符,导致查询条件匹配失败。
解决方案
方案1:使用NamedParameterJdbcTemplate(推荐,适配你已有代码)
Spring提供的NamedParameterJdbcTemplate原生支持IN子句的集合参数传参,你已经定义了MapSqlParameterSource,修改成本方案成本极低。
改造步骤:
- 替换DAO中注入的JdbcTemplate为NamedParameterJdbcTemplate
- 改写SQL为命名参数格式,用
:countryName作为IN子句的参数 - 调用NamedParameterJdbcTemplate的query方法执行查询
改造后代码:
@Component public class CountryMasterDAO implements CountryMasterService{ // 注入命名参数JdbcTemplate,Spring Boot环境会自动装配,无需手动配置 @Autowired private NamedParameterJdbcTemplate namedParameterJdbcTemplate; @Override public List<String> getCountryData(String compCode, CountryMasterModel model) throws SQLException, DataAccessException { List<String> ids = Arrays.asList(model.getCountryNames()); MapSqlParameterSource parameters = new MapSqlParameterSource(); parameters.addValue("countryName", ids); // 用命名参数写法写SQL String sql = "SELECT NAME FROM country_master WHERE NAME IN (:countryName)"; // 执行查询 return namedParameterJdbcTemplate.query(sql, parameters, new CountryMasterResultSetExtrator()); } // main方法测试逻辑保持不变即可 }
方案2:手动生成占位符(无需引入NamedParameterJdbcTemplate)
如果坚持使用基础JdbcTemplate,可以根据参数数量动态生成对应个数的?占位符,拼接进SQL:
@Override public List<String> getCountryData(String compCode, CountryMasterModel model) throws SQLException, DataAccessException { List<String> ids = Arrays.asList(model.getCountryNames()); // 生成和参数数量一致的?,用逗号分隔 String placeholders = String.join(",", Collections.nCopies(ids.size(), "?")); String sql = "SELECT NAME FROM country_master WHERE NAME IN (" + placeholders + ")"; // 参数直接传列表转数组即可 return template.query(sql, ids.toArray(), new CountryMasterResultSetExtrator()); }
额外注意点
- 你当前代码中已经
@Autowired注入了JdbcTemplate,但是方法内又手动new JdbcTemplate(DBMSSQL.getDBCon()),会覆盖注入的实例,每次调用都会新建连接,容易引发连接泄漏,建议删除手动new的逻辑,直接使用容器注入的实例 - 你的
CountryMasterService接口中定义的getCountryData方法包含compCode和model两个参数,实现类的方法参数列表和接口不一致,会导致编译或注入错误,需要修正参数列表
内容的提问来源于stack exchange,提问作者Prince
相关产品推荐
相关产品推荐

