Skip to content

Commit 56ad839

Browse files
committed
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.
1 parent 8ecc01d commit 56ad839

File tree

4 files changed

+39
-1
lines changed

4 files changed

+39
-1
lines changed

spring-data-jdbc/src/main/java/org/springframework/data/jdbc/repository/query/JdbcQueryMethod.java

+10
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,15 @@ private String getNamedQuery() {
151151
return this.namedQueries.hasQuery(name) ? this.namedQueries.getQuery(name) : null;
152152
}
153153

154+
/**
155+
* @return {@literal true} if the method is annotated with {@code @Query(name=…)}.
156+
*/
157+
public boolean hasAnnotatedQueryName() {
158+
return lookupQueryAnnotation() //
159+
.map(Query::name) //
160+
.map(StringUtils::hasText).orElse(false);
161+
}
162+
154163
@Override
155164
public String getNamedQueryName() {
156165

@@ -159,6 +168,7 @@ public String getNamedQueryName() {
159168
return StringUtils.hasText(annotatedName) ? annotatedName : super.getNamedQueryName();
160169
}
161170

171+
162172
/**
163173
* Returns the class to be used as {@link org.springframework.jdbc.core.RowMapper}
164174
*

spring-data-jdbc/src/main/java/org/springframework/data/jdbc/repository/query/StringBasedJdbcQuery.java

+2-1
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
import org.springframework.lang.Nullable;
3535
import org.springframework.util.Assert;
3636
import org.springframework.util.ClassUtils;
37+
import org.springframework.util.ObjectUtils;
3738
import org.springframework.util.StringUtils;
3839

3940
/**
@@ -143,7 +144,7 @@ private String determineQuery() {
143144

144145
String query = queryMethod.getDeclaredQuery();
145146

146-
if (StringUtils.isEmpty(query)) {
147+
if (ObjectUtils.isEmpty(query)) {
147148
throw new IllegalStateException(String.format("No query specified on %s", queryMethod.getName()));
148149
}
149150

spring-data-jdbc/src/main/java/org/springframework/data/jdbc/repository/support/JdbcQueryLookupStrategy.java

+10
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,9 @@
1919
import java.sql.ResultSet;
2020
import java.sql.SQLException;
2121

22+
import org.apache.commons.logging.Log;
23+
import org.apache.commons.logging.LogFactory;
24+
2225
import org.springframework.beans.factory.BeanFactory;
2326
import org.springframework.context.ApplicationEventPublisher;
2427
import org.springframework.data.jdbc.core.convert.EntityRowMapper;
@@ -58,6 +61,8 @@
5861
*/
5962
class JdbcQueryLookupStrategy implements QueryLookupStrategy {
6063

64+
private static final Log LOG = LogFactory.getLog(JdbcQueryLookupStrategy.class);
65+
6166
private final ApplicationEventPublisher publisher;
6267
private final @Nullable EntityCallbacks callbacks;
6368
private final RelationalMappingContext context;
@@ -103,6 +108,11 @@ public RepositoryQuery resolveQuery(Method method, RepositoryMetadata repository
103108
try {
104109
if (namedQueries.hasQuery(queryMethod.getNamedQueryName()) || queryMethod.hasAnnotatedQuery()) {
105110

111+
if (queryMethod.hasAnnotatedQuery() && queryMethod.hasAnnotatedQueryName()) {
112+
LOG.warn(String.format(
113+
"Query method %s is annotated with both, a query and a query name. Using the declared query.", method));
114+
}
115+
106116
RowMapper<?> mapper = queryMethod.isModifyingQuery() ? null : createMapper(queryMethod);
107117
StringBasedJdbcQuery query = new StringBasedJdbcQuery(queryMethod, operations, mapper, converter);
108118
query.setBeanFactory(beanfactory);

spring-data-jdbc/src/test/java/org/springframework/data/jdbc/repository/support/JdbcQueryLookupStrategyUnitTests.java

+17
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,20 @@ public void typeBasedRowMapperGetsUsedForQuery() {
8888
verify(operations).queryForObject(anyString(), any(SqlParameterSource.class), any(RowMapper.class));
8989
}
9090

91+
@Test // GH-1061
92+
public void prefersDeclaredQuery() {
93+
94+
RowMapper<? extends NumberFormat> numberFormatMapper = mock(RowMapper.class);
95+
QueryMappingConfiguration mappingConfiguration = new DefaultQueryMappingConfiguration()
96+
.registerRowMapper(NumberFormat.class, numberFormatMapper);
97+
98+
RepositoryQuery repositoryQuery = getRepositoryQuery("annotatedQueryWithQueryAndQueryName", mappingConfiguration);
99+
100+
repositoryQuery.execute(new Object[] {});
101+
102+
verify(operations).queryForObject(eq("some SQL"), any(SqlParameterSource.class), any(RowMapper.class));
103+
}
104+
91105
private RepositoryQuery getRepositoryQuery(String name, QueryMappingConfiguration mappingConfiguration) {
92106

93107
JdbcQueryLookupStrategy queryLookupStrategy = new JdbcQueryLookupStrategy(publisher, callbacks, mappingContext,
@@ -102,5 +116,8 @@ interface MyRepository {
102116
// NumberFormat is just used as an arbitrary non simple type.
103117
@Query("some SQL")
104118
NumberFormat returningNumberFormat();
119+
120+
@Query(value = "some SQL", name = "query-name")
121+
void annotatedQueryWithQueryAndQueryName();
105122
}
106123
}

0 commit comments

Comments
 (0)