Skip to content

Commit

Permalink
Try to parse SpEL expressions in @query sooner.
Browse files Browse the repository at this point in the history
  • Loading branch information
gregturn committed Sep 7, 2023
1 parent 075fdc5 commit 763ff18
Show file tree
Hide file tree
Showing 7 changed files with 42 additions and 6 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@

import java.util.List;

import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.lang.Nullable;
import org.springframework.util.ObjectUtils;

Expand All @@ -37,7 +38,30 @@ 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, null);
}

/**
* Creates a {@literal DeclaredQuery} from a query {@literal String}.
*
* @param query might be {@literal null} or empty.
* @param nativeQuery is a given query is native or not
* @param entityMetadata metadata about the repository's related type
* @param parser a {@link SpelExpressionParser} used to process potential SpEL expressions found in the query
* @return a {@literal DeclaredQuery} instance even for a {@literal null} or empty argument.
*/
static DeclaredQuery of(@Nullable String query, boolean nativeQuery, @Nullable JpaEntityMetadata<?> entityMetadata,
@Nullable SpelExpressionParser parser) {

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

if (entityMetadata != null) {
return new ExpressionBasedStringQuery(query, entityMetadata, 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
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ 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(), this.getEntityInformation(), JpaQueryFactory.PARSER).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 @@ -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() {

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

0 comments on commit 763ff18

Please sign in to comment.