Skip to content

Support dynamic SQL provider for @Query methods - #2333

Open
benelog wants to merge 1 commit into
spring-projects:mainfrom
benelog:gh-542-dynamic-sql-provider
Open

Support dynamic SQL provider for @Query methods#2333
benelog wants to merge 1 commit into
spring-projects:mainfrom
benelog:gh-542-dynamic-sql-provider

Conversation

@benelog

@benelog benelog commented Jul 25, 2026

Copy link
Copy Markdown
Contributor
  • You have read the Spring Data contribution guidelines.
  • You use the code formatters provided here and have them applied to your changes. Don’t submit any formatting related changes.
  • You submit test cases (unit or integration tests) that back your changes.
  • You added yourself as author in the headers of the classes you touched. Amend the date range in the Apache license header if needed. For new types, add the license header (copy from another file and set the current year only).

Introduce a QueryProvider SPI that generates the SQL statement for a repository query method at runtime, based on the bound parameter values, following the design discussed in #542. A provider implementation is configured via the new queryProviderClass attribute of @Query, while parameter binding, query execution, and result mapping remain handled by Spring Data JDBC:

interface ProductRepository extends CrudRepository<Product, String> {

    @Query(queryProviderClass = ProductQueryProvider.class)
    List<Product> findByName(@Param("name") @Nullable String name);
}

class ProductQueryProvider implements QueryProvider {

    @Override
    public String getQuery(SqlParameterSource source) {

        String sql = "SELECT * FROM product";
        return isNotNull(source, "name") ? sql + " WHERE name = :name" : sql;
    }
}

Changes:

  • New QueryProvider functional interface (getQuery(SqlParameterSource) plus isNotNull/isNotEmpty default helpers) in org.springframework.data.jdbc.repository.query.
  • New @Query(queryProviderClass = …) attribute, mutually exclusive with value and name. The configured class gets instantiated through its default constructor, following the rowMapperClass conventions.
  • StringBasedJdbcQuery obtains the SQL statement from the provider on every invocation after parameter binding. Custom RowMapper/ResultSetExtractor configuration applies as for any other @Query method. Value expressions and #{#tableName} preprocessing are not applied to provider-generated SQL.
  • DeclaredQueryLookupStrategy resolves provider methods first and reports invalid combinations (value/name together with a provider, non-instantiable provider classes) with IllegalArgumentException so that CREATE_IF_NOT_FOUND does not silently fall back to query derivation.
  • Query methods using a QueryProvider are excluded from AOT repository generation and resolve at runtime.
  • Reference documentation section for dynamic queries.

Closes #542

@spring-projects-issues spring-projects-issues added the status: waiting-for-triage An issue we've not yet triaged label Jul 25, 2026
Introduce the QueryProvider SPI generating the SQL statement to execute at runtime, based on the bound parameter values. A provider implementation can be configured via @query(queryProviderClass = …) while parameter binding, query execution, and result mapping remain handled by Spring Data JDBC. Query methods using a QueryProvider are excluded from AOT repository generation and resolve at runtime.

Closes spring-projects#542

Signed-off-by: Sanghyuk Jung <sanghyuk.jung@navercorp.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

status: waiting-for-triage An issue we've not yet triaged

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Support dynamic SQL provider [DATAJDBC-319]

2 participants