Refine NamedQuery error messages when using Sort/Pageable parameters.

Closes #3660
This commit is contained in:
Mark Paluch
2024-12-09 14:25:53 +01:00
parent 7f13a04c41
commit a1be5bc1b5
3 changed files with 15 additions and 23 deletions

View File

@@ -22,7 +22,6 @@ import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Optional;
import java.util.Set;
@@ -70,20 +69,10 @@ public class JpaQueryMethod extends QueryMethod {
* Persistence Specification: Persistent Fields and Properties - Paragraph starting with
* "Collection-valued persistent...".</a>
*/
private static final Set<Class<?>> NATIVE_ARRAY_TYPES;
private static final Set<Class<?>> NATIVE_ARRAY_TYPES = Set.of(byte[].class, Byte[].class, char[].class,
Character[].class);
private static final StoredProcedureAttributeSource storedProcedureAttributeSource = StoredProcedureAttributeSource.INSTANCE;
static {
Set<Class<?>> types = new HashSet<>();
types.add(byte[].class);
types.add(Byte[].class);
types.add(char[].class);
types.add(Character[].class);
NATIVE_ARRAY_TYPES = Collections.unmodifiableSet(types);
}
private final QueryExtractor extractor;
private final Method method;
private final Class<?> returnType;

View File

@@ -69,8 +69,9 @@ final class NamedQuery extends AbstractJpaQuery {
Parameters<?, ?> parameters = method.getParameters();
if (parameters.hasSortParameter()) {
throw new IllegalStateException(String.format("Finder method %s is backed by a NamedQuery and must "
+ "not contain a sort parameter as we cannot modify the query; Use @Query instead", method));
throw new IllegalStateException(String.format("Query method %s is backed by a NamedQuery and must "
+ "not contain a sort parameter as we cannot modify the query; Use @%s(value=…) instead to apply sorting or remove the 'Sort' parameter.",
method, method.isNativeQuery() ? "NativeQuery" : "Query"));
}
this.namedCountQueryIsPresent = hasNamedQuery(em, countQueryName);
@@ -85,14 +86,14 @@ final class NamedQuery extends AbstractJpaQuery {
if (parameters.hasPageableParameter()) {
LOG.warn(String.format(
"Finder method %s is backed by a NamedQuery but contains a Pageable parameter; Sorting delivered via this Pageable will not be applied",
method));
"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.",
method, method.isNativeQuery() ? "NativeQuery" : "Query"));
}
String queryString = extractor.extractQueryString(query);
// TODO: Detect whether a named query is a native one.
this.declaredQuery = Lazy.of(() -> DeclaredQuery.of(queryString, query.toString().contains("NativeQuery")));
this.declaredQuery = Lazy
.of(() -> DeclaredQuery.of(queryString, method.isNativeQuery() || query.toString().contains("NativeQuery")));
this.metadataCache = new QueryParameterSetter.QueryMetadataCache();
}
@@ -133,7 +134,7 @@ final class NamedQuery extends AbstractJpaQuery {
String queryName = method.getNamedQueryName();
if (LOG.isDebugEnabled()) {
LOG.debug(String.format("Looking up named query %s", queryName));
LOG.debug(String.format("Looking up named query '%s'", queryName));
}
if (!hasNamedQuery(em, queryName)) {
@@ -141,12 +142,14 @@ final class NamedQuery extends AbstractJpaQuery {
}
if (method.isScrollQuery()) {
throw QueryCreationException.create(method, "Scroll queries are not supported using String-based queries");
throw QueryCreationException.create(method, String.format(
"Scroll queries are not supported using String-based queries as we cannot rewrite the query string. Use @%s(value=…) instead.",
method.isNativeQuery() ? "NativeQuery" : "Query"));
}
RepositoryQuery query = new NamedQuery(method, em);
if (LOG.isDebugEnabled()) {
LOG.debug(String.format("Found named query %s", queryName));
LOG.debug(String.format("Found named query '%s'", queryName));
}
return query;
}

View File

@@ -163,7 +163,7 @@ class JpaQueryLookupStrategyUnitTests {
assertThatIllegalStateException()
.isThrownBy(() -> strategy.resolveQuery(method, metadata, projectionFactory, namedQueries))
.withMessageContaining(
"is backed by a NamedQuery and must not contain a sort parameter as we cannot modify the query; Use @Query instead");
"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.");
}
@Test // GH-2018