Skip to content

Commit e4a2416

Browse files
committed
Refine NamedQuery error messages when using Sort/Pageable parameters.
Closes #3660
1 parent eb9f746 commit e4a2416

File tree

3 files changed

+15
-23
lines changed

3 files changed

+15
-23
lines changed

spring-data-jpa/src/main/java/org/springframework/data/jpa/repository/query/JpaQueryMethod.java

+2-13
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@
2222
import java.lang.reflect.Method;
2323
import java.util.Arrays;
2424
import java.util.Collections;
25-
import java.util.HashSet;
2625
import java.util.List;
2726
import java.util.Optional;
2827
import java.util.Set;
@@ -70,20 +69,10 @@ public class JpaQueryMethod extends QueryMethod {
7069
* Persistence Specification: Persistent Fields and Properties - Paragraph starting with
7170
* "Collection-valued persistent...".</a>
7271
*/
73-
private static final Set<Class<?>> NATIVE_ARRAY_TYPES;
72+
private static final Set<Class<?>> NATIVE_ARRAY_TYPES = Set.of(byte[].class, Byte[].class, char[].class,
73+
Character[].class);
7474
private static final StoredProcedureAttributeSource storedProcedureAttributeSource = StoredProcedureAttributeSource.INSTANCE;
7575

76-
static {
77-
78-
Set<Class<?>> types = new HashSet<>();
79-
types.add(byte[].class);
80-
types.add(Byte[].class);
81-
types.add(char[].class);
82-
types.add(Character[].class);
83-
84-
NATIVE_ARRAY_TYPES = Collections.unmodifiableSet(types);
85-
}
86-
8776
private final QueryExtractor extractor;
8877
private final Method method;
8978
private final Class<?> returnType;

spring-data-jpa/src/main/java/org/springframework/data/jpa/repository/query/NamedQuery.java

+12-9
Original file line numberDiff line numberDiff line change
@@ -69,8 +69,9 @@ private NamedQuery(JpaQueryMethod method, EntityManager em) {
6969
Parameters<?, ?> parameters = method.getParameters();
7070

7171
if (parameters.hasSortParameter()) {
72-
throw new IllegalStateException(String.format("Finder method %s is backed by a NamedQuery and must "
73-
+ "not contain a sort parameter as we cannot modify the query; Use @Query instead", method));
72+
throw new IllegalStateException(String.format("Query method %s is backed by a NamedQuery and must "
73+
+ "not contain a sort parameter as we cannot modify the query; Use @%s(value=…) instead to apply sorting or remove the 'Sort' parameter.",
74+
method, method.isNativeQuery() ? "NativeQuery" : "Query"));
7475
}
7576

7677
this.namedCountQueryIsPresent = hasNamedQuery(em, countQueryName);
@@ -85,14 +86,14 @@ private NamedQuery(JpaQueryMethod method, EntityManager em) {
8586

8687
if (parameters.hasPageableParameter()) {
8788
LOG.warn(String.format(
88-
"Finder method %s is backed by a NamedQuery but contains a Pageable parameter; Sorting delivered via this Pageable will not be applied",
89-
method));
89+
"Query method %s is backed by a NamedQuery but contains a Pageable parameter; Sorting delivered via this Pageable will not be applied; Use @%s(value=…) instead to apply sorting.",
90+
method, method.isNativeQuery() ? "NativeQuery" : "Query"));
9091
}
9192

9293
String queryString = extractor.extractQueryString(query);
9394

94-
// TODO: Detect whether a named query is a native one.
95-
this.declaredQuery = Lazy.of(() -> DeclaredQuery.of(queryString, query.toString().contains("NativeQuery")));
95+
this.declaredQuery = Lazy
96+
.of(() -> DeclaredQuery.of(queryString, method.isNativeQuery() || query.toString().contains("NativeQuery")));
9697
this.metadataCache = new QueryParameterSetter.QueryMetadataCache();
9798
}
9899

@@ -133,20 +134,22 @@ public static RepositoryQuery lookupFrom(JpaQueryMethod method, EntityManager em
133134
String queryName = method.getNamedQueryName();
134135

135136
if (LOG.isDebugEnabled()) {
136-
LOG.debug(String.format("Looking up named query %s", queryName));
137+
LOG.debug(String.format("Looking up named query '%s'", queryName));
137138
}
138139

139140
if (!hasNamedQuery(em, queryName)) {
140141
return null;
141142
}
142143

143144
if (method.isScrollQuery()) {
144-
throw QueryCreationException.create(method, "Scroll queries are not supported using String-based queries");
145+
throw QueryCreationException.create(method, String.format(
146+
"Scroll queries are not supported using String-based queries as we cannot rewrite the query string. Use @%s(value=…) instead.",
147+
method.isNativeQuery() ? "NativeQuery" : "Query"));
145148
}
146149

147150
RepositoryQuery query = new NamedQuery(method, em);
148151
if (LOG.isDebugEnabled()) {
149-
LOG.debug(String.format("Found named query %s", queryName));
152+
LOG.debug(String.format("Found named query '%s'", queryName));
150153
}
151154
return query;
152155
}

spring-data-jpa/src/test/java/org/springframework/data/jpa/repository/query/JpaQueryLookupStrategyUnitTests.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -163,7 +163,7 @@ void namedQueryWithSortShouldThrowIllegalStateException() throws NoSuchMethodExc
163163
assertThatIllegalStateException()
164164
.isThrownBy(() -> strategy.resolveQuery(method, metadata, projectionFactory, namedQueries))
165165
.withMessageContaining(
166-
"is backed by a NamedQuery and must not contain a sort parameter as we cannot modify the query; Use @Query instead");
166+
"is backed by a NamedQuery and must not contain a sort parameter as we cannot modify the query; Use @Query(value=…) instead to apply sorting or remove the 'Sort' parameter.");
167167
}
168168

169169
@Test // GH-2018

0 commit comments

Comments
 (0)