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

Spring JdbcTemplate tenant predicates: put ownership in the SQL query

Last updated: 30 Sept 20264 min read
tutorial
IntermediateBy AITrove Editorial

A tenant-scoped repository query includes the trusted tenant identifier in its database predicate for every read or write.

Download Spring source kit

The same receipt ID exists twice

The H2 fixture stores R-41 for tenant-east and tenant-west with different states. Querying by receipt ID and tenant ID returns accepted for east, held for west and no row for a third tenant. The authenticated web request for east reaches that query; a west route under the east token is denied by method security before query execution. The two checks cover separate boundaries.

Do not fetch by receipt ID alone and filter afterward. That can disclose the wrong row through logging, caching, serialization or a later code path. Use the trusted identity mapped in JWT validation, then bind it as a SQL parameter. For writes, include tenant_id and expected state or version in the update predicate, and inspect the affected row count. The earlier write fixture is only an in-memory service rule.

Keys and plans matter

The fixture uses a composite primary key (receipt_id, tenant_id). A real schema should choose an index order based on its query patterns and verify the plan on the target database. The predicate is an application safeguard; database row-level security can add another independent boundary if the platform supports it. Never form SQL identifiers from tenant text.

Checked source

Java
String state = jdbc.queryForObject(
    "select state from tenant_receipt where receipt_id = ? and tenant_id = ?",
    String.class, "R-41", trustedTenant);

Verification boundary

JwtTenantBoundaryTest.scopedQueryExcludesRowsForOtherTenantValues and JwtTenantBoundaryTest.trustedTenantClaimPassesTheMatchingServiceRule runs in the downloadable Spring source kit. The excerpt is shortened; the kit contains the complete test.

Costs and limits

The test checks three tenant values against two H2 rows and one authenticated request. It does not prove target-database plans, row-level security, large-table latency or that every application repository uses the predicate. An indexed point lookup is expected to scale with index depth plus returned rows; measure the chosen schema.

Common Mistakes

  • Do not query by receipt ID and filter in Java afterward.
  • Do not pass a URL or header tenant into SQL without a membership decision.
  • Do not ignore a zero-row update in a tenant-scoped write.

Read next

Spring Security JWT tenant principal: map only a validated claim, Spring Security scope versus tenant ownership: two separate decisions, Spring method security: reject a cross-tenant receipt mutation, Spring JdbcTemplate: bound values and visible database constraints.

Continue with checked tenant commands

Continue with Spring JDBC versioned tenant update: inspect the affected row count.

Continue with checked settings and schema rollout

Continue with Spring database backfill: assign historical rows before enforcing ownership.

spring
spring-boot
tenant-jdbc-predicate
Storage details