Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Properly handle native queries with SpEL #3109

Closed
wants to merge 3 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

<groupId>org.springframework.data</groupId>
<artifactId>spring-data-jpa-parent</artifactId>
<version>3.2.0-SNAPSHOT</version>
<version>3.2.0-gh-3096-SNAPSHOT</version>
<packaging>pom</packaging>

<name>Spring Data JPA Parent</name>
Expand Down
4 changes: 2 additions & 2 deletions spring-data-envers/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,12 @@

<groupId>org.springframework.data</groupId>
<artifactId>spring-data-envers</artifactId>
<version>3.2.0-SNAPSHOT</version>
<version>3.2.0-gh-3096-SNAPSHOT</version>

<parent>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-jpa-parent</artifactId>
<version>3.2.0-SNAPSHOT</version>
<version>3.2.0-gh-3096-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

Expand Down
2 changes: 1 addition & 1 deletion spring-data-jpa-distribution/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
<parent>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-jpa-parent</artifactId>
<version>3.2.0-SNAPSHOT</version>
<version>3.2.0-gh-3096-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

Expand Down
4 changes: 2 additions & 2 deletions spring-data-jpa/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

<groupId>org.springframework.data</groupId>
<artifactId>spring-data-jpa</artifactId>
<version>3.2.0-SNAPSHOT</version>
<version>3.2.0-gh-3096-SNAPSHOT</version>

<name>Spring Data JPA</name>
<description>Spring Data module for JPA repositories.</description>
Expand All @@ -15,7 +15,7 @@
<parent>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-jpa-parent</artifactId>
<version>3.2.0-SNAPSHOT</version>
<version>3.2.0-gh-3096-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
*
* @author Jens Schauder
* @author Diego Krupitza
* @author Greg Turnquist
* @since 2.0.3
*/
interface DeclaredQuery {
Expand All @@ -37,7 +38,28 @@ interface DeclaredQuery {
* @return a {@literal DeclaredQuery} instance even for a {@literal null} or empty argument.
*/
static DeclaredQuery of(@Nullable String query, boolean nativeQuery) {
return ObjectUtils.isEmpty(query) ? EmptyDeclaredQuery.EMPTY_QUERY : new StringQuery(query, nativeQuery);
return of(query, nativeQuery, null);
}

/**
* Creates a {@literal DeclaredQuery} from a query {@literal String} and the related {@link JpaQueryMethod}.
*
* @param query might be {@literal null} or empty.
* @param nativeQuery is a given query is native or not
* @param entityMetadata is a {@link JpaEntityMetadata} that might be {@literal null}
* @return a {@literal DeclaredQuery} instance even for a {@literal null} or empty argument.
*/
static DeclaredQuery of(@Nullable String query, Boolean nativeQuery, @Nullable JpaEntityMetadata<?> entityMetadata) {

if (ObjectUtils.isEmpty(query)) {
return EmptyDeclaredQuery.EMPTY_QUERY;
}

if (ExpressionBasedStringQuery.containsExpression(query) && entityMetadata != null) {
return new ExpressionBasedStringQuery(query, entityMetadata, JpaQueryFactory.PARSER, nativeQuery);
}

return new StringQuery(query, nativeQuery);
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ class ExpressionBasedStringQuery extends StringQuery {
*/
public ExpressionBasedStringQuery(String query, JpaEntityMetadata<?> metadata, SpelExpressionParser parser,
boolean nativeQuery) {
super(renderQueryIfExpressionOrReturnQuery(query, metadata, parser), nativeQuery && !containsExpression(query));
super(renderQueryIfExpressionOrReturnQuery(query, metadata, parser), nativeQuery);
}

/**
Expand Down Expand Up @@ -118,7 +118,10 @@ private static String potentiallyQuoteExpressionsParameter(String query) {
return EXPRESSION_PARAMETER_QUOTING.matcher(query).replaceAll(QUOTED_EXPRESSION_PARAMETER);
}

private static boolean containsExpression(String query) {
/**
* Does the {@literal query} contains a SpEL expression?
*/
static boolean containsExpression(String query) {
return query.contains(ENTITY_NAME_VARIABLE_EXPRESSION);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -29,12 +29,13 @@
*
* @author Thomas Darimont
* @author Mark Paluch
* @author Greg Turnquist
*/
enum JpaQueryFactory {

INSTANCE;

private static final SpelExpressionParser PARSER = new SpelExpressionParser();
static final SpelExpressionParser PARSER = new SpelExpressionParser();

/**
* Creates a {@link RepositoryQuery} from the given {@link String} query.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,7 @@ private void assertParameterNamesInAnnotatedQuery() {

String annotatedQuery = getAnnotatedQuery();

if (!DeclaredQuery.of(annotatedQuery, this.isNativeQuery.get()).hasNamedParameter()) {
if (!DeclaredQuery.of(annotatedQuery, this.isNativeQuery.get(), getEntityInformation()).hasNamedParameter()) {
return;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1073,6 +1073,14 @@ void shouldSupportModifyingQueryWithVarArgs() {
assertThat(repository.findByActiveTrue()).isEmpty();
}

@Test // GH-3096
void shouldSupportNativeQueriesWithSpEL() {

flushTestUsers();

assertThat(repository.nativeQueryWithSpEL()).containsExactly(firstUser, secondUser, thirdUser, fourthUser);
}

@Test // DATAJPA-405
void executesFinderWithOrderClauseOnly() {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ void shouldDetectBindParameterCountCorrectlyWithJDBCStyleParameters() {
}

@Test
void shouldDetectComplexNativeQueriesWithSpelAsNonNative() {
void shouldDetectComplexNativeQueriesWithSpelAsRetainingNativeQueryStatus() {

StringQuery query = new ExpressionBasedStringQuery(
"select n from #{#entityName} n where (LOWER(n.name) LIKE LOWER(NULLIF(text(concat('%',?#{#networkRequest.name},'%')), '')) OR ?#{#networkRequest.name} IS NULL )"
Expand All @@ -106,15 +106,15 @@ void shouldDetectComplexNativeQueriesWithSpelAsNonNative() {
+ "AND (n.updatedAt >= ?#{#networkRequest.updatedTime.startDateTime}) AND (n.updatedAt <=?#{#networkRequest.updatedTime.endDateTime})",
metadata, SPEL_PARSER, true);

assertThat(query.isNativeQuery()).isFalse();
assertThat(query.isNativeQuery()).isTrue();
}

@Test
void shouldDetectSimpleNativeQueriesWithSpelAsNonNative() {
void shouldDetectSimpleNativeQueriesWithSpelAsRetainingNativeQueryStatus() {

StringQuery query = new ExpressionBasedStringQuery("select n from #{#entityName} n", metadata, SPEL_PARSER, true);

assertThat(query.isNativeQuery()).isFalse();
assertThat(query.isNativeQuery()).isTrue();
}

@Test
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -734,6 +734,10 @@ List<String> findAllAndSortByFunctionResultNamedParameter(@Param("namedParameter
@Query("select u from User u where u.firstname >= (select Min(u0.firstname) from User u0)")
List<NameOnly> findProjectionBySubselect();

// GH-3096
@Query(value = "select * from SD_User as #{#entityName}", nativeQuery = true)
List<User> nativeQueryWithSpEL();

Window<User> findBy(OffsetScrollPosition position);

interface RolesAndFirstname {
Expand Down