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 #1061.
This commit is contained in:
Mark Paluch
2021-10-06 09:03:36 +02:00
parent bc866e3a06
commit 09596ce1eb
4 changed files with 39 additions and 1 deletions

View File

@@ -151,6 +151,15 @@ public class JdbcQueryMethod extends QueryMethod {
return this.namedQueries.hasQuery(name) ? this.namedQueries.getQuery(name) : null;
}
/**
* @return {@literal true} if the method is annotated with {@code @Query(name=…)}.
*/
public boolean hasAnnotatedQueryName() {
return lookupQueryAnnotation() //
.map(Query::name) //
.map(StringUtils::hasText).orElse(false);
}
@Override
public String getNamedQueryName() {
@@ -159,6 +168,7 @@ public class JdbcQueryMethod extends QueryMethod {
return StringUtils.hasText(annotatedName) ? annotatedName : super.getNamedQueryName();
}
/**
* Returns the class to be used as {@link org.springframework.jdbc.core.RowMapper}
*

View File

@@ -40,6 +40,7 @@ import org.springframework.jdbc.core.namedparam.NamedParameterJdbcOperations;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;
/**
@@ -175,7 +176,7 @@ public class StringBasedJdbcQuery extends AbstractJdbcQuery {
String query = queryMethod.getDeclaredQuery();
if (StringUtils.isEmpty(query)) {
if (ObjectUtils.isEmpty(query)) {
throw new IllegalStateException(String.format("No query specified on %s", queryMethod.getName()));
}

View File

@@ -19,6 +19,9 @@ import java.lang.reflect.Method;
import java.sql.ResultSet;
import java.sql.SQLException;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.data.jdbc.core.convert.EntityRowMapper;
@@ -60,6 +63,8 @@ import org.springframework.util.Assert;
*/
class JdbcQueryLookupStrategy implements QueryLookupStrategy {
private static final Log LOG = LogFactory.getLog(JdbcQueryLookupStrategy.class);
private final ApplicationEventPublisher publisher;
private final @Nullable EntityCallbacks callbacks;
private final RelationalMappingContext context;
@@ -105,6 +110,11 @@ class JdbcQueryLookupStrategy implements QueryLookupStrategy {
try {
if (namedQueries.hasQuery(queryMethod.getNamedQueryName()) || queryMethod.hasAnnotatedQuery()) {
if (queryMethod.hasAnnotatedQuery() && queryMethod.hasAnnotatedQueryName()) {
LOG.warn(String.format(
"Query method %s is annotated with both, a query and a query name. Using the declared query.", method));
}
StringBasedJdbcQuery query = new StringBasedJdbcQuery(queryMethod, operations, this::createMapper, converter);
query.setBeanFactory(beanfactory);
return query;

View File

@@ -88,6 +88,20 @@ public class JdbcQueryLookupStrategyUnitTests {
verify(operations).queryForObject(anyString(), any(SqlParameterSource.class), any(RowMapper.class));
}
@Test // GH-1061
public void prefersDeclaredQuery() {
RowMapper<? extends NumberFormat> numberFormatMapper = mock(RowMapper.class);
QueryMappingConfiguration mappingConfiguration = new DefaultQueryMappingConfiguration()
.registerRowMapper(NumberFormat.class, numberFormatMapper);
RepositoryQuery repositoryQuery = getRepositoryQuery("annotatedQueryWithQueryAndQueryName", mappingConfiguration);
repositoryQuery.execute(new Object[] {});
verify(operations).queryForObject(eq("some SQL"), any(SqlParameterSource.class), any(RowMapper.class));
}
private RepositoryQuery getRepositoryQuery(String name, QueryMappingConfiguration mappingConfiguration) {
JdbcQueryLookupStrategy queryLookupStrategy = new JdbcQueryLookupStrategy(publisher, callbacks, mappingContext,
@@ -102,5 +116,8 @@ public class JdbcQueryLookupStrategyUnitTests {
// NumberFormat is just used as an arbitrary non simple type.
@Query("some SQL")
NumberFormat returningNumberFormat();
@Query(value = "some SQL", name = "query-name")
void annotatedQueryWithQueryAndQueryName();
}
}