Skip to content
AITroveRead. Build. Understand.
Make this comfortable

Spring NamedParameterJdbcTemplate: expand an ID list without dropping tenant scope

Last updated: 1 Oct 20264 min read
tutorial
IntermediateBy AITrove Editorial

NamedParameterJdbcTemplate binds a collection into an IN clause while other named parameters remain part of the SQL predicate.

Download Spring source kit

Keep the ownership predicate in SQL

The fixture asks for three receipt IDs, but one belongs to another tenant. The query binds both tenantId and receiptIds; the result contains only the two rows owned by TENANT-A. Filtering rows after a broader query would allow unauthorized records to leave the database boundary and can waste I/O.

Collection expansion is for values, not arbitrary SQL identifiers. Never splice an untrusted comma-separated string into the SQL grammar. Tenant predicates explains why the ownership condition must appear in the database statement, and prepared values covers the lower-level boundary.

Cap the list before building SQL

Each ID becomes a bound value. A huge list increases SQL size, parameter count and planning work; databases also differ in parameter limits. Define a maximum batch size and decide what an empty list means before executing, since an empty IN clause has no useful portable SQL shape.

Checked code

Java
var parameters = new MapSqlParameterSource()
        .addValue("tenantId", "TENANT-A")
        .addValue("receiptIds", List.of(47L, 82L, 91L));
var matches = named.queryForList(
        "select receipt_id from receipt_route where tenant_id = :tenantId " +
        "and receipt_id in (:receiptIds) order by receipt_id",
        parameters, Long.class);

Verification boundary

The Maven source kit passes JdbcParametersAndKeysContractTest.namedCollectionParameterKeepsTenantPredicateInTheQuery on its local Spring Boot 4 and Java 21 fixture.

Cost and ownership

The fixture scans a tiny H2 table. Real cost depends on tenant cardinality, ID count, indexes and the database planner. The query returns O(k) IDs for k matches and holds the supplied list and result in memory; benchmark the target database before choosing a batch cap.

Common Mistakes

  • Do not remove tenant_id from the SQL and filter the returned rows in Java.
  • Do not interpolate IDs or a tenant string directly into SQL.
  • Do not pass an unbounded or empty ID collection without a defined policy.

Read next

Spring JdbcTemplate: bound values and visible database constraints, Spring JdbcTemplate tenant predicates: put ownership in the SQL query, Java JDBC PreparedStatement: values stay outside SQL grammar, Spring Boot JDBC pool capacity: size connections across replicas.

spring
spring-boot
named-parameter-jdbc-list
Storage details