Skip to content

Commit f43cd80

Browse files
committed
Improve query method validation exceptions for declared queries.
When validating manually declared queries on repositories, the exception that captures the query to validate now actually also reports it in the exception message. Related ticket: #2736.
1 parent f260d17 commit f43cd80

File tree

2 files changed

+21
-18
lines changed

2 files changed

+21
-18
lines changed

Diff for: spring-data-jpa/src/main/java/org/springframework/data/jpa/repository/query/SimpleJpaQuery.java

+18-15
Original file line numberDiff line numberDiff line change
@@ -41,37 +41,39 @@ final class SimpleJpaQuery extends AbstractStringBasedJpaQuery {
4141
*
4242
* @param method must not be {@literal null}
4343
* @param em must not be {@literal null}
44-
* @param countQueryString
44+
* @param sourceQuery the original source query, must not be {@literal null} or empty.
4545
* @param queryRewriter must not be {@literal null}
4646
* @param evaluationContextProvider must not be {@literal null}
4747
* @param parser must not be {@literal null}
4848
*/
49-
public SimpleJpaQuery(JpaQueryMethod method, EntityManager em, @Nullable String countQueryString,
50-
QueryRewriter queryRewriter, QueryMethodEvaluationContextProvider evaluationContextProvider, SpelExpressionParser parser) {
51-
this(method, em, method.getRequiredAnnotatedQuery(), countQueryString, queryRewriter, evaluationContextProvider, parser);
49+
public SimpleJpaQuery(JpaQueryMethod method, EntityManager em, @Nullable String sourceQuery,
50+
QueryRewriter queryRewriter, QueryMethodEvaluationContextProvider evaluationContextProvider,
51+
SpelExpressionParser parser) {
52+
this(method, em, method.getRequiredAnnotatedQuery(), sourceQuery, queryRewriter, evaluationContextProvider,
53+
parser);
5254
}
5355

5456
/**
5557
* Creates a new {@link SimpleJpaQuery} that encapsulates a simple query string.
5658
*
5759
* @param method must not be {@literal null}
5860
* @param em must not be {@literal null}
59-
* @param queryString must not be {@literal null} or empty
61+
* @param sourceQuery the original source query, must not be {@literal null} or empty
6062
* @param countQueryString
6163
* @param queryRewriter
6264
* @param evaluationContextProvider must not be {@literal null}
6365
* @param parser must not be {@literal null}
6466
*/
65-
public SimpleJpaQuery(JpaQueryMethod method, EntityManager em, String queryString, @Nullable String countQueryString, QueryRewriter queryRewriter,
66-
QueryMethodEvaluationContextProvider evaluationContextProvider, SpelExpressionParser parser) {
67+
public SimpleJpaQuery(JpaQueryMethod method, EntityManager em, String sourceQuery, @Nullable String countQueryString,
68+
QueryRewriter queryRewriter, QueryMethodEvaluationContextProvider evaluationContextProvider,
69+
SpelExpressionParser parser) {
6770

68-
super(method, em, queryString, countQueryString, queryRewriter, evaluationContextProvider, parser);
71+
super(method, em, sourceQuery, countQueryString, queryRewriter, evaluationContextProvider, parser);
6972

70-
validateQuery(getQuery().getQueryString(), "Validation failed for query for method %s", method);
73+
validateQuery(getQuery(), "Validation failed for query %s for method %s", method);
7174

7275
if (method.isPageQuery()) {
73-
validateQuery(getCountQuery().getQueryString(),
74-
String.format("Count query validation failed for method %s", method));
76+
validateQuery(getCountQuery(), "Count query %s validation failed for method %s", method);
7577
}
7678
}
7779

@@ -81,23 +83,24 @@ public SimpleJpaQuery(JpaQueryMethod method, EntityManager em, String queryStrin
8183
* @param query
8284
* @param errorMessage
8385
*/
84-
private void validateQuery(String query, String errorMessage, Object... arguments) {
86+
private void validateQuery(DeclaredQuery query, String errorMessage, JpaQueryMethod method) {
8587

8688
if (getQueryMethod().isProcedureQuery()) {
8789
return;
8890
}
8991

9092
EntityManager validatingEm = null;
93+
var queryString = query.getQueryString();
9194

9295
try {
9396
validatingEm = getEntityManager().getEntityManagerFactory().createEntityManager();
94-
validatingEm.createQuery(query);
97+
validatingEm.createQuery(queryString);
9598

9699
} catch (RuntimeException e) {
97100

98101
// Needed as there's ambiguities in how an invalid query string shall be expressed by the persistence provider
99-
// https://java.net/projects/jpa-spec/lists/jsr338-experts/archive/2012-07/message/17
100-
throw new IllegalArgumentException(String.format(errorMessage, arguments), e);
102+
// https://download.oracle.com/javaee-archive/jpa-spec.java.net/users/2012/07/0404.html
103+
throw new IllegalArgumentException(errorMessage.formatted(query, method), e);
101104

102105
} finally {
103106

Diff for: spring-data-jpa/src/test/java/org/springframework/data/jpa/repository/query/SimpleJpaQueryUnitTests.java

+3-3
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,6 @@
3737
import org.mockito.junit.jupiter.MockitoExtension;
3838
import org.mockito.junit.jupiter.MockitoSettings;
3939
import org.mockito.quality.Strictness;
40-
4140
import org.springframework.data.domain.Page;
4241
import org.springframework.data.domain.PageRequest;
4342
import org.springframework.data.domain.Pageable;
@@ -175,14 +174,15 @@ void doesNotValidateCountQueryIfNotPagingMethod() throws Exception {
175174
}
176175

177176
@Test // DATAJPA-352
178-
@SuppressWarnings("unchecked")
179177
void validatesAndRejectsCountQueryIfPagingMethod() throws Exception {
180178

181179
Method method = SampleRepository.class.getMethod("pageByAnnotatedQuery", Pageable.class);
182180

183181
when(em.createQuery(Mockito.contains("count"))).thenThrow(IllegalArgumentException.class);
184182

185-
assertThatIllegalArgumentException().isThrownBy(() -> createJpaQuery(method)).withMessageContaining("Count")
183+
assertThatIllegalArgumentException() //
184+
.isThrownBy(() -> createJpaQuery(method)) //
185+
.withMessageContaining("Count") //
186186
.withMessageContaining(method.getName());
187187
}
188188

0 commit comments

Comments
 (0)