From fa11454bd93f529a5fb8fae9bfb35341251c06a5 Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Wed, 6 Oct 2021 09:32:25 +0200 Subject: [PATCH] Log a warning when a query method is annotated with a query and a query name. We now log when a query method has an ambiguous declaration to clarify that the declared query is used. Closes #2319 --- .../query/JpaQueryLookupStrategy.java | 10 ++++++++++ .../jpa/repository/query/JpaQueryMethod.java | 8 ++++++++ .../query/JpaQueryLookupStrategyUnitTests.java | 17 +++++++++++++++++ 3 files changed, 35 insertions(+) diff --git a/src/main/java/org/springframework/data/jpa/repository/query/JpaQueryLookupStrategy.java b/src/main/java/org/springframework/data/jpa/repository/query/JpaQueryLookupStrategy.java index 0cb10ca92..89d592420 100644 --- a/src/main/java/org/springframework/data/jpa/repository/query/JpaQueryLookupStrategy.java +++ b/src/main/java/org/springframework/data/jpa/repository/query/JpaQueryLookupStrategy.java @@ -19,6 +19,9 @@ import java.lang.reflect.Method; import javax.persistence.EntityManager; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + import org.springframework.data.jpa.repository.Query; import org.springframework.data.projection.ProjectionFactory; import org.springframework.data.repository.core.NamedQueries; @@ -40,6 +43,8 @@ import org.springframework.util.Assert; */ public final class JpaQueryLookupStrategy { + private static final Logger LOG = LoggerFactory.getLogger(JpaQueryLookupStrategy.class); + /** * Private constructor to prevent instantiation. */ @@ -145,6 +150,11 @@ public final class JpaQueryLookupStrategy { RepositoryQuery query = JpaQueryFactory.INSTANCE.fromQueryAnnotation(method, em, evaluationContextProvider); + if (query != null && method.hasAnnotatedQueryName()) { + LOG.warn(String.format( + "Query method %s is annotated with both, a query and a query name. Using the declared query.", method)); + } + if (null != query) { return query; } diff --git a/src/main/java/org/springframework/data/jpa/repository/query/JpaQueryMethod.java b/src/main/java/org/springframework/data/jpa/repository/query/JpaQueryMethod.java index 4e19f3280..37a3cbdce 100644 --- a/src/main/java/org/springframework/data/jpa/repository/query/JpaQueryMethod.java +++ b/src/main/java/org/springframework/data/jpa/repository/query/JpaQueryMethod.java @@ -274,6 +274,13 @@ public class JpaQueryMethod extends QueryMethod { return StringUtils.hasText(query) ? query : null; } + /** + * @return {@code true} if this method is annotated with {@code @Query(name=…)}. + */ + boolean hasAnnotatedQueryName() { + return StringUtils.hasText(getAnnotationValue("name", String.class)); + } + /** * Returns the required query string declared in a {@link Query} annotation or throws {@link IllegalStateException} if * neither the annotation found nor the attribute was specified. @@ -442,4 +449,5 @@ public class JpaQueryMethod extends QueryMethod { return storedProcedureAttributes; } + } diff --git a/src/test/java/org/springframework/data/jpa/repository/query/JpaQueryLookupStrategyUnitTests.java b/src/test/java/org/springframework/data/jpa/repository/query/JpaQueryLookupStrategyUnitTests.java index d2b9ed30c..c5b8f7bac 100644 --- a/src/test/java/org/springframework/data/jpa/repository/query/JpaQueryLookupStrategyUnitTests.java +++ b/src/test/java/org/springframework/data/jpa/repository/query/JpaQueryLookupStrategyUnitTests.java @@ -46,6 +46,7 @@ import org.springframework.data.repository.core.support.DefaultRepositoryMetadat import org.springframework.data.repository.query.QueryLookupStrategy; import org.springframework.data.repository.query.QueryLookupStrategy.Key; import org.springframework.data.repository.query.QueryMethodEvaluationContextProvider; +import org.springframework.data.repository.query.RepositoryQuery; /** * Unit tests for {@link JpaQueryLookupStrategy}. @@ -110,6 +111,19 @@ public class JpaQueryLookupStrategyUnitTests { .withMessageContaining(method.toString()); } + @Test // GH-2319 + void prefersDeclaredQuery() throws Exception { + + QueryLookupStrategy strategy = JpaQueryLookupStrategy.create(em, queryMethodFactory, Key.CREATE_IF_NOT_FOUND, + EVALUATION_CONTEXT_PROVIDER, EscapeCharacter.DEFAULT); + Method method = UserRepository.class.getMethod("annotatedQueryWithQueryAndQueryName"); + RepositoryMetadata metadata = new DefaultRepositoryMetadata(UserRepository.class); + + RepositoryQuery repositoryQuery = strategy.resolveQuery(method, metadata, projectionFactory, namedQueries); + + assertThat(repositoryQuery).isInstanceOf(AbstractStringBasedJpaQuery.class); + } + interface UserRepository extends Repository { @Query("something absurd") @@ -117,5 +131,8 @@ public class JpaQueryLookupStrategyUnitTests { @Query(value = "select u.* from User u", nativeQuery = true) List findByInvalidNativeQuery(String param, Sort sort); + + @Query(value = "something absurd", name = "my-query-name") + User annotatedQueryWithQueryAndQueryName(); } }