You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring Boot中使用JdbcTemplate执行带IN子句和多参数的SQL查询实现方法

实现方案

下面分别提供两种常用实现方式:

方案1:使用NamedParameterJdbcTemplate(推荐)

Spring提供的NamedParameterJdbcTemplate原生支持集合类型参数,无需手动拼接占位符,可避免SQL注入风险,是处理IN/NOT IN场景的最优选择。
Spring Boot环境已默认自动配置该类,直接注入即可使用,示例代码如下:

import org.springframework.jdbc.core.namedparam.MapSqlParameterSource;
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
import java.util.List;
import java.util.Map;

@Repository
public class OrderDetailDao {
    @Autowired
    private NamedParameterJdbcTemplate namedParameterJdbcTemplate;

    // SQL语句直接用命名参数占位,NOT IN部分直接写:messageCodes即可
    private static final String QUERY_SQL = """
        SELECT *
        FROM order_details
        WHERE store_nbr = :storeNbr
          AND div_nbr = :divNbr
          AND ordered_item = :orderedItem
          AND message_code NOT IN (:messageCodes)
          AND DATE(order_date) = DATE(:orderDate)
    """;

    public List<Map<String, Object>> queryOrderDetails(Integer storeNbr, Integer divNbr, String orderedItem, List<String> messageCodes, String orderDate) {
        MapSqlParameterSource paramSource = new MapSqlParameterSource();
        paramSource.addValue("storeNbr", storeNbr);
        paramSource.addValue("divNbr", divNbr);
        paramSource.addValue("orderedItem", orderedItem);
        paramSource.addValue("messageCodes", messageCodes); // 直接传入集合,框架自动生成对应数量的占位符
        paramSource.addValue("orderDate", orderDate);
        
        // 如需映射为实体类,可替换为query方法配合RowMapper使用
        return namedParameterJdbcTemplate.queryForList(QUERY_SQL, paramSource);
    }
}

方案2:使用原生JdbcTemplate实现

如果必须使用原生JdbcTemplate,需要手动拼接NOT IN部分的占位符,再按顺序组装所有参数,示例代码如下:

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Repository;
import java.util.List;
import java.util.Map;

@Repository
public class OrderDetailDao {
    @Autowired
    private JdbcTemplate jdbcTemplate;

    public List<Map<String, Object>> queryOrderDetails(Integer storeNbr, Integer divNbr, String orderedItem, List<String> messageCodes, String orderDate) {
        // 1. 生成NOT IN对应的占位符串,比如集合长度为3就生成?,?,?
        String inPlaceholders = String.join(",", messageCodes.stream().map(code -> "?").toArray(String[]::new));
        // 2. 拼接完整SQL
        String querySql = String.format("""
            SELECT *
            FROM order_details
            WHERE store_nbr = ?
              AND div_nbr = ?
              AND ordered_item = ?
              AND message_code NOT IN (%s)
              AND DATE(order_date) = DATE(?)
        """, inPlaceholders);
        
        // 3. 按SQL占位符顺序组装参数数组
        Object[] params = new Object[3 + messageCodes.size() + 1];
        params[0] = storeNbr;
        params[1] = divNbr;
        params[2] = orderedItem;
        int index = 3;
        for (String code : messageCodes) {
            params[index++] = code;
        }
        params[index] = orderDate;
        
        return jdbcTemplate.queryForList(querySql, params);
    }
}

注意:如果messageCodes集合为空,NOT IN ()会触发SQL语法错误,需要提前判断集合为空的场景,要么跳过该条件,要么做特殊逻辑处理。

内容的提问来源于stack exchange,提问作者Jolly George

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.07 16:18:01