Using a List of Values in a JdbcTemplate IN Clause

1. Introduction

In a SQL statement, we can use the IN operator to test whether an expression matches any value in a list. Therefore, we can use the IN operator instead of multiple OR conditions.

In this tutorial, we’ll show how to pass a list of values into the IN clause of a Spring JDBC template query.

2. Passing a List Parameter to IN Clause

The IN operator allows us to specify multiple values in a WHERE clause. For example, we can use it to find all employees whose id is in a specified id list:

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

Typically, the total number of values inside the IN clause is variable. Therefore, we need to create a placeholder that can support a dynamic list of values.

2.1. With JdbcTemplate

With JdbcTemplate, we can use ‘?’ characters as placeholders for the list of values. The number of ‘?’ characters will be the same as the size of the list:

List<Employee> getEmployeesFromIdList(List<Integer> ids) {
    String inSql = String.join(",", Collections.nCopies(ids.size(), "?"));
 
    List<Employee> employees = jdbcTemplate.query(
      String.format("SELECT * FROM EMPLOYEE WHERE id IN (%s)", inSql), 
      ids.toArray(), 
      (rs, rowNum) -> new Employee(rs.getInt("id"), rs.getString("first_name"), 
        rs.getString("last_name")));

    return employees;
}

In this method, we first generate a placeholder string that contains ids.size() ‘?’ characters separated with commas. Then, we put this string into the IN clause of our SQL statement. For example, if we have three numbers in the ids list, the SQL statement is:

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

In the query method, we pass the ids list as a parameter to match the placeholders inside the IN clause. This way, we can execute a dynamic SQL statement based on the input list of values.

2.2. With NamedParameterJdbcTemplate

Another way to handle the dynamic list of values is to use NamedParameterJdbcTemplate. For example, we can directly create a named parameter for the input list:

List<Employee> getEmployeesFromIdListNamed(List<Integer> ids) {
    SqlParameterSource parameters = new MapSqlParameterSource("ids", ids);
 
    List<Employee> employees = namedJdbcTemplate.query(
      "SELECT * FROM EMPLOYEE WHERE id IN (:ids)", 
      parameters, 
      (rs, rowNum) -> new Employee(rs.getInt("id"), rs.getString("first_name"),
        rs.getString("last_name")));

    return employees;
}

In this method, we first construct a MapSqlParameterSource object that contains the input id list. Then, we only use one named parameter to represent the dynamic list of values.

Under the hood, NamedParameterJdbcTemplate substitutes the named parameters for the ‘?’ placeholders and uses JdbcTemplate to execute the query.

3. Handling a Large List

When we have a large number of values in a list, we should consider alternative ways to pass them into the JdbcTemplate query.

For example, the Oracle database doesn’t support more than 1,000 literals in an IN clause.

One way to do that is to create a temporary table for the list. However, different databases can have different ways to create temporary tables. For example, we can use the CREATE GLOBAL TEMPORARY TABLE statement to create a temporary table in the Oracle database.

Let’s create a temporary table for the H2 database:

List<Employee> getEmployeesFromLargeIdList(List<Integer> ids) {
    jdbcTemplate.execute("CREATE TEMPORARY TABLE IF NOT EXISTS employee_tmp (id INT NOT NULL)");

    List<Object[]> employeeIds = new ArrayList<>();
    for (Integer id : ids) {
        employeeIds.add(new Object[] { id });
    }
    jdbcTemplate.batchUpdate("INSERT INTO employee_tmp VALUES(?)", employeeIds);

    List<Employee> employees = jdbcTemplate.query(
      "SELECT * FROM EMPLOYEE WHERE id IN (SELECT id FROM employee_tmp)", 
      (rs, rowNum) -> new Employee(rs.getInt("id"), rs.getString("first_name"),
      rs.getString("last_name")));

    jdbcTemplate.update("DELETE FROM employee_tmp");
 
    return employees;
}

Here, we first create a temporary table to hold all values of the input list. Then, we insert the input list’s values into this table.

In our resulting SQL statement, the values in the IN clause are from the temporary table, and we’ve avoided constructing an IN clause with a large number of placeholders.

Finally, after we finish the query, we clean up the temporary table for future reuse.

4. Conclusion

In this tutorial, we showed how to use JdbcTemplate and NamedParameterJdbcTemplate to pass a list of values for the IN clause of a SQL query. Also, we provided an alternative way to handle a large number of list values by using a temporary table.

As always, the source code for the article is available over on GitHub.

Related posts:

Introduction to Spring Method Security
Spring Boot - Twilio
Spring Boot - Application Properties
Java Program to Implement Shunting Yard Algorithm
Using Spring @ResponseStatus to Set HTTP Status Code
Spring Boot: Customize Whitelabel Error Page
Java Program to Represent Graph Using Incidence List
SOAP Web service: Authentication trong JAX-WS
Java Program to Implement Sorted Array
Java Program to Test Using DFS Whether a Directed Graph is Weakly Connected or Not
Remove HTML tags from a file to extract only the TEXT
An Introduction to Java.util.Hashtable Class
Kết hợp Java Reflection và Java Annotations
A Quick Guide to Spring MVC Matrix Variables
An Introduction to ThreadLocal in Java
Sao chép các phần tử của một mảng sang mảng khác như thế nào?
Java – Get Random Item/Element From a List
Serve Static Resources with Spring
Java Program to Implement Knight’s Tour Problem
Converting Strings to Enums in Java
Spring Boot - Eureka Server
Java Program to Implement Branch and Bound Method to Perform a Combinatorial Search
Concatenating Strings In Java
Java Program to Find the Median of two Sorted Arrays using Binary Search Approach
Java Program to Represent Graph Using 2D Arrays
Debugging Reactive Streams in Java
Creating a Custom Starter with Spring Boot
Retrieve User Information in Spring Security
Java Program to Perform Right Rotation on a Binary Search Tree
Generating Random Dates in Java
Java Program to Check Whether an Undirected Graph Contains a Eulerian Path
Java Program to Implement Rolling Hash