• 在 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语句里有太多参数。

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

  • 相关阅读:
    System.arraycopy数组拷贝
    Linux环境下通过SDK海康摄像头登录失败
    Vue系列(一)之 Vue入门,Vue的生命周期以及前后端分离介绍
    C++版本的OpenCV实现二维图像的卷积定理(通过傅里叶变换实现二维图像的卷积过程,附代码!!)
    老卫带你学---leetcode刷题(557. 反转字符串中的单词 III)
    LightDB兼容Oracle table_exists_action功能
    TiDB 内存控制文档
    java-php-python-毕业生交流学习平台计算机毕业设计
    CSS超出两行隐藏
    [图论]哈尔滨工业大学(哈工大 HIT)学习笔记40-53
  • 原文地址:https://blog.csdn.net/ldx891113/article/details/127577823