• 在 JdbcTemplate IN 子句中使用List动态参数


    我们将学习如何将List传递到 Spring JDBC 模板查询的 IN 子句中。

    SELECT * FROM EMPLOYEE WHERE id IN (1, 2, 3)

     IN子句里是固定长度的不在今天的讨论范围。通常情况下IN子句里的值数量是可变的,因此我们需要创建一个可以支持动态List的占位符。

    第一种方式:用JdbcTemplate

    1. List getEmployeesFromIdList(List ids) {
    2. String inSql = String.join(",", Collections.nCopies(ids.size(), "?"));
    3. List employees = jdbcTemplate.query(
    4. String.format("SELECT * FROM EMPLOYEE WHERE id IN (%s)", inSql),
    5. ids.toArray(),
    6. (rs, rowNum) -> new Employee(rs.getInt("id"), rs.getString("first_name"),
    7. rs.getString("last_name")));
    8. return employees;
    9. }

    首先我们先生成一个List长度的用逗号分隔的“?”占位符字符串,然后拼接到IN子句里。比如我们ids的List的长度为3,生成的SQL声明如下:

    SELECT * FROM EMPLOYEE WHERE id IN (?,?,?)

     我们用ids List做为参数。通过这种方式,我们能够基于输入的List执行动态SQL。

    第二种方式:用NamedParameterJdbcTemplate

    另一种执行不固定长度的List做为IN子句条件的方法是用 NamedParameterJdbcTemplate 。

    如:

    1. List getEmployeesFromIdListNamed(List ids) {
    2. SqlParameterSource parameters = new MapSqlParameterSource("ids", ids);
    3. List employees = namedJdbcTemplate.query(
    4. "SELECT * FROM EMPLOYEE WHERE id IN (:ids)",
    5. parameters,
    6. (rs, rowNum) -> new Employee(rs.getInt("id"), rs.getString("first_name"),
    7. rs.getString("last_name")));
    8. return employees;
    9. }

    超大List做IN子句

    当List中有大量值时,我们应该考虑将List传递给 JdbcTemplate 查询的替代方法。

    例如,IN语句中可放的最大参数个数是1000个。mysql中,IN语句中参数个数是不限制的。不过对整段sql语句的长度有了限制(max_allowed_packet)。

    遇到这种情况 ,可以为List创建一个临时表。不过需要注意的是,不同数据库有不同的方法来创建临时表。比如,我们能用“CREATE GLOBAL TEMPORARY TABLE ”语句在Oracle数据库里创建临时表。

    1. List getEmployeesFromLargeIdList(List ids) {
    2. jdbcTemplate.execute("CREATE TEMPORARY TABLE IF NOT EXISTS employee_tmp (id INT NOT NULL)");
    3. List employeeIds = new ArrayList<>();
    4. for (Integer id : ids) {
    5. employeeIds.add(new Object[] { id });
    6. }
    7. jdbcTemplate.batchUpdate("INSERT INTO employee_tmp VALUES(?)", employeeIds);
    8. List employees = jdbcTemplate.query(
    9. "SELECT * FROM EMPLOYEE WHERE id IN (SELECT id FROM employee_tmp)",
    10. (rs, rowNum) -> new Employee(rs.getInt("id"), rs.getString("first_name"),
    11. rs.getString("last_name")));
    12. jdbcTemplate.update("DELETE FROM employee_tmp");
    13. return employees;
    14. }

    我们首先创建一个临时表,然后将List值insert到临时表。

    在IN语句里的值从临时表里查询获取,通过这种方式我们可以避免IN语句里有太多参数。

    最后我们完成查询后,删除掉临时表以便以后在用。

  • 相关阅读:
    java序列化与反序列化
    【源码】SpringBoot事务注册原理
    VS 常用的快捷键指令
    ChatTTS 开源文本转语音模型本地部署、API使用和搭建WebUI界面(建议收藏)
    Linux json-c使用
    从零开始使用git
    (附源码)app校园购物网站 毕业设计 041037
    站在巨人肩膀上学习,京东爆款架构师成长手册首发
    【单链表增删查改接口的实现】
    Docker-概念及配置(超详细)
  • 原文地址:https://blog.csdn.net/ldx891113/article/details/127577823