From 7a9e55f8cfe66889d0be770a0c176de4dcf7dac7 Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Thu, 23 Feb 2023 15:55:31 +0100 Subject: [PATCH] Delay count query derivation. We now delay the count query creation to the actual time when we need the count query to avoid query creation of invalid queries (e.g. count queries for DELETE or UPDATE statements). See #2812 --- .../query/AbstractStringBasedJpaQuery.java | 21 +++++++++---------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/spring-data-jpa/src/main/java/org/springframework/data/jpa/repository/query/AbstractStringBasedJpaQuery.java b/spring-data-jpa/src/main/java/org/springframework/data/jpa/repository/query/AbstractStringBasedJpaQuery.java index e3a2ff1ce..cf22cc9f4 100644 --- a/spring-data-jpa/src/main/java/org/springframework/data/jpa/repository/query/AbstractStringBasedJpaQuery.java +++ b/spring-data-jpa/src/main/java/org/springframework/data/jpa/repository/query/AbstractStringBasedJpaQuery.java @@ -18,15 +18,13 @@ package org.springframework.data.jpa.repository.query; import jakarta.persistence.EntityManager; import jakarta.persistence.Query; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Sort; import org.springframework.data.jpa.repository.QueryRewriter; import org.springframework.data.repository.query.QueryMethodEvaluationContextProvider; import org.springframework.data.repository.query.ResultProcessor; import org.springframework.data.repository.query.ReturnedType; +import org.springframework.data.util.Lazy; import org.springframework.expression.spel.standard.SpelExpressionParser; import org.springframework.lang.Nullable; import org.springframework.util.Assert; @@ -46,7 +44,7 @@ import org.springframework.util.Assert; abstract class AbstractStringBasedJpaQuery extends AbstractJpaQuery { private final DeclaredQuery query; - private final DeclaredQuery countQuery; + private final Lazy countQuery; private final QueryMethodEvaluationContextProvider evaluationContextProvider; private final SpelExpressionParser parser; private final QueryParameterSetter.QueryMetadataCache metadataCache = new QueryParameterSetter.QueryMetadataCache(); @@ -65,8 +63,8 @@ abstract class AbstractStringBasedJpaQuery extends AbstractJpaQuery { * @param queryRewriter must not be {@literal null}. */ public AbstractStringBasedJpaQuery(JpaQueryMethod method, EntityManager em, String queryString, - @Nullable String countQueryString, QueryRewriter queryRewriter, QueryMethodEvaluationContextProvider evaluationContextProvider, - SpelExpressionParser parser) { + @Nullable String countQueryString, QueryRewriter queryRewriter, + QueryMethodEvaluationContextProvider evaluationContextProvider, SpelExpressionParser parser) { super(method, em); @@ -79,9 +77,10 @@ abstract class AbstractStringBasedJpaQuery extends AbstractJpaQuery { this.query = new ExpressionBasedStringQuery(queryString, method.getEntityInformation(), parser, method.isNativeQuery()); - DeclaredQuery countQuery = query.deriveCountQuery(countQueryString, method.getCountQueryProjection()); - this.countQuery = ExpressionBasedStringQuery.from(countQuery, method.getEntityInformation(), parser, - method.isNativeQuery()); + this.countQuery = Lazy.of(() -> { + DeclaredQuery countQuery = query.deriveCountQuery(countQueryString, method.getCountQueryProjection()); + return ExpressionBasedStringQuery.from(countQuery, method.getEntityInformation(), parser, method.isNativeQuery()); + }); this.parser = parser; this.queryRewriter = queryRewriter; @@ -117,7 +116,7 @@ abstract class AbstractStringBasedJpaQuery extends AbstractJpaQuery { @Override protected Query doCreateCountQuery(JpaParametersParameterAccessor accessor) { - String queryString = countQuery.getQueryString(); + String queryString = countQuery.get().getQueryString(); EntityManager em = getEntityManager(); Query query = getQueryMethod().isNativeQuery() // @@ -142,7 +141,7 @@ abstract class AbstractStringBasedJpaQuery extends AbstractJpaQuery { * @return the countQuery */ public DeclaredQuery getCountQuery() { - return countQuery; + return countQuery.get(); } /**