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
This commit is contained in:
Mark Paluch
2021-10-06 09:32:25 +02:00
parent a88b90a6b1
commit fa11454bd9
3 changed files with 35 additions and 0 deletions

View File

@@ -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;
}

View File

@@ -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;
}
}

View File

@@ -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<User, Integer> {
@Query("something absurd")
@@ -117,5 +131,8 @@ public class JpaQueryLookupStrategyUnitTests {
@Query(value = "select u.* from User u", nativeQuery = true)
List<User> findByInvalidNativeQuery(String param, Sort sort);
@Query(value = "something absurd", name = "my-query-name")
User annotatedQueryWithQueryAndQueryName();
}
}