From d854c63f120d04757eb57bb450262bfdb08b80d3 Mon Sep 17 00:00:00 2001 From: Oliver Drotbohm Date: Wed, 21 Dec 2022 22:21:14 +0100 Subject: [PATCH] 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. Closes: #2736. Original pull request: #2738 --- .../jpa/repository/query/SimpleJpaQuery.java | 28 +++++++++---------- .../query/SimpleJpaQueryUnitTests.java | 6 ++-- 2 files changed, 17 insertions(+), 17 deletions(-) diff --git a/spring-data-jpa/src/main/java/org/springframework/data/jpa/repository/query/SimpleJpaQuery.java b/spring-data-jpa/src/main/java/org/springframework/data/jpa/repository/query/SimpleJpaQuery.java index c9a80e4a3..f84cd46c9 100644 --- a/spring-data-jpa/src/main/java/org/springframework/data/jpa/repository/query/SimpleJpaQuery.java +++ b/spring-data-jpa/src/main/java/org/springframework/data/jpa/repository/query/SimpleJpaQuery.java @@ -40,13 +40,13 @@ final class SimpleJpaQuery extends AbstractStringBasedJpaQuery { * * @param method must not be {@literal null} * @param em must not be {@literal null} - * @param countQueryString + * @param sourceQuery the original source query, must not be {@literal null} or empty. * @param queryRewriter must not be {@literal null} * @param valueExpressionDelegate must not be {@literal null} */ - public SimpleJpaQuery(JpaQueryMethod method, EntityManager em, @Nullable String countQueryString, + public SimpleJpaQuery(JpaQueryMethod method, EntityManager em, @Nullable String sourceQuery, QueryRewriter queryRewriter, ValueExpressionDelegate valueExpressionDelegate) { - this(method, em, method.getRequiredAnnotatedQuery(), countQueryString, queryRewriter, valueExpressionDelegate); + this(method, em, method.getRequiredAnnotatedQuery(), sourceQuery, queryRewriter, valueExpressionDelegate); } /** @@ -54,21 +54,20 @@ final class SimpleJpaQuery extends AbstractStringBasedJpaQuery { * * @param method must not be {@literal null} * @param em must not be {@literal null} - * @param queryString must not be {@literal null} or empty + * @param sourceQuery the original source query, must not be {@literal null} or empty * @param countQueryString * @param queryRewriter * @param valueExpressionDelegate must not be {@literal null} */ - public SimpleJpaQuery(JpaQueryMethod method, EntityManager em, String queryString, @Nullable String countQueryString, QueryRewriter queryRewriter, - ValueExpressionDelegate valueExpressionDelegate) { + public SimpleJpaQuery(JpaQueryMethod method, EntityManager em, String sourceQuery, @Nullable String countQueryString, + QueryRewriter queryRewriter, ValueExpressionDelegate valueExpressionDelegate) { - super(method, em, queryString, countQueryString, queryRewriter, valueExpressionDelegate); + super(method, em, sourceQuery, countQueryString, queryRewriter, valueExpressionDelegate); - validateQuery(getQuery().getQueryString(), "Validation failed for query for method %s", method); + validateQuery(getQuery(), "Validation failed for query %s for method %s", method); if (method.isPageQuery()) { - validateQuery(getCountQuery().getQueryString(), - String.format("Count query validation failed for method %s", method)); + validateQuery(getCountQuery(), "Count query %s validation failed for method %s", method); } } @@ -78,23 +77,24 @@ final class SimpleJpaQuery extends AbstractStringBasedJpaQuery { * @param query * @param errorMessage */ - private void validateQuery(String query, String errorMessage, Object... arguments) { + private void validateQuery(DeclaredQuery query, String errorMessage, JpaQueryMethod method) { if (getQueryMethod().isProcedureQuery()) { return; } EntityManager validatingEm = null; + var queryString = query.getQueryString(); try { validatingEm = getEntityManager().getEntityManagerFactory().createEntityManager(); - validatingEm.createQuery(query); + validatingEm.createQuery(queryString); } catch (RuntimeException e) { // Needed as there's ambiguities in how an invalid query string shall be expressed by the persistence provider - // https://java.net/projects/jpa-spec/lists/jsr338-experts/archive/2012-07/message/17 - throw new IllegalArgumentException(String.format(errorMessage, arguments), e); + // https://download.oracle.com/javaee-archive/jpa-spec.java.net/users/2012/07/0404.html + throw new IllegalArgumentException(errorMessage.formatted(query, method), e); } finally { diff --git a/spring-data-jpa/src/test/java/org/springframework/data/jpa/repository/query/SimpleJpaQueryUnitTests.java b/spring-data-jpa/src/test/java/org/springframework/data/jpa/repository/query/SimpleJpaQueryUnitTests.java index 45c247040..66b8edf89 100644 --- a/spring-data-jpa/src/test/java/org/springframework/data/jpa/repository/query/SimpleJpaQueryUnitTests.java +++ b/spring-data-jpa/src/test/java/org/springframework/data/jpa/repository/query/SimpleJpaQueryUnitTests.java @@ -40,7 +40,6 @@ import org.mockito.Mockito; import org.mockito.junit.jupiter.MockitoExtension; import org.mockito.junit.jupiter.MockitoSettings; import org.mockito.quality.Strictness; - import org.springframework.data.domain.Page; import org.springframework.data.domain.PageRequest; import org.springframework.data.domain.Pageable; @@ -194,14 +193,15 @@ class SimpleJpaQueryUnitTests { } @Test // DATAJPA-352 - @SuppressWarnings("unchecked") void validatesAndRejectsCountQueryIfPagingMethod() throws Exception { Method method = SampleRepository.class.getMethod("pageByAnnotatedQuery", Pageable.class); when(em.createQuery(Mockito.contains("count"))).thenThrow(IllegalArgumentException.class); - assertThatIllegalArgumentException().isThrownBy(() -> createJpaQuery(method)).withMessageContaining("Count") + assertThatIllegalArgumentException() // + .isThrownBy(() -> createJpaQuery(method)) // + .withMessageContaining("Count") // .withMessageContaining(method.getName()); }