diff --git a/pom.xml b/pom.xml
index ade6f22b06..8ba05e1147 100755
--- a/pom.xml
+++ b/pom.xml
@@ -5,7 +5,7 @@
org.springframework.data
spring-data-jpa-parent
- 4.0.0-SNAPSHOT
+ 4.0.0-GH-3588-SNAPSHOT
pom
Spring Data JPA Parent
diff --git a/spring-data-envers/pom.xml b/spring-data-envers/pom.xml
index 0bdf2c8e7e..3782a4af3e 100755
--- a/spring-data-envers/pom.xml
+++ b/spring-data-envers/pom.xml
@@ -5,12 +5,12 @@
org.springframework.data
spring-data-envers
- 4.0.0-SNAPSHOT
+ 4.0.0-GH-3588-SNAPSHOT
org.springframework.data
spring-data-jpa-parent
- 4.0.0-SNAPSHOT
+ 4.0.0-GH-3588-SNAPSHOT
../pom.xml
diff --git a/spring-data-jpa-distribution/pom.xml b/spring-data-jpa-distribution/pom.xml
index af5244a230..e2e4a70a89 100644
--- a/spring-data-jpa-distribution/pom.xml
+++ b/spring-data-jpa-distribution/pom.xml
@@ -14,7 +14,7 @@
org.springframework.data
spring-data-jpa-parent
- 4.0.0-SNAPSHOT
+ 4.0.0-GH-3588-SNAPSHOT
../pom.xml
diff --git a/spring-data-jpa/pom.xml b/spring-data-jpa/pom.xml
index ae5a4738dc..7fff0fe902 100644
--- a/spring-data-jpa/pom.xml
+++ b/spring-data-jpa/pom.xml
@@ -6,7 +6,7 @@
org.springframework.data
spring-data-jpa
- 4.0.0-SNAPSHOT
+ 4.0.0-GH-3588-SNAPSHOT
Spring Data JPA
Spring Data module for JPA repositories.
@@ -15,7 +15,7 @@
org.springframework.data
spring-data-jpa-parent
- 4.0.0-SNAPSHOT
+ 4.0.0-GH-3588-SNAPSHOT
../pom.xml
diff --git a/spring-data-jpa/src/main/java/org/springframework/data/jpa/repository/query/AbstractJpaQuery.java b/spring-data-jpa/src/main/java/org/springframework/data/jpa/repository/query/AbstractJpaQuery.java
index 5742a1ea4e..1ecedcee11 100644
--- a/spring-data-jpa/src/main/java/org/springframework/data/jpa/repository/query/AbstractJpaQuery.java
+++ b/spring-data-jpa/src/main/java/org/springframework/data/jpa/repository/query/AbstractJpaQuery.java
@@ -235,8 +235,8 @@ private Query applyLockMode(Query query, JpaQueryMethod method) {
return lockModeType == null ? query : query.setLockMode(lockModeType);
}
- protected ParameterBinder createBinder() {
- return ParameterBinderFactory.createBinder(getQueryMethod().getParameters());
+ ParameterBinder createBinder() {
+ return ParameterBinderFactory.createBinder(getQueryMethod().getParameters(), false);
}
protected Query createQuery(JpaParametersParameterAccessor parameters) {
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 0d257fe5a2..9c83985546 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
@@ -51,7 +51,6 @@ abstract class AbstractStringBasedJpaQuery extends AbstractJpaQuery {
private final DeclaredQuery query;
private final Lazy countQuery;
private final ValueExpressionDelegate valueExpressionDelegate;
- private final QueryParameterSetter.QueryMetadataCache metadataCache = new QueryParameterSetter.QueryMetadataCache();
private final QueryRewriter queryRewriter;
private final QuerySortRewriter querySortRewriter;
private final Lazy countParameterBinder;
@@ -121,11 +120,9 @@ public Query doCreateQuery(JpaParametersParameterAccessor accessor) {
Query query = createJpaQuery(sortedQueryString, sort, accessor.getPageable(), processor.getReturnedType());
- QueryParameterSetter.QueryMetadata metadata = metadataCache.getMetadata(sortedQueryString, query);
-
// it is ok to reuse the binding contained in the ParameterBinder although we create a new query String because the
// parameters in the query do not change.
- return parameterBinder.get().bindAndPrepare(query, metadata, accessor);
+ return parameterBinder.get().bindAndPrepare(query, accessor);
}
String getSortedQueryString(Sort sort) {
@@ -152,9 +149,8 @@ protected Query doCreateCountQuery(JpaParametersParameterAccessor accessor) {
? em.createNativeQuery(queryString) //
: em.createQuery(queryString, Long.class);
- QueryParameterSetter.QueryMetadata metadata = metadataCache.getMetadata(queryString, query);
-
- countParameterBinder.get().bind(metadata.withQuery(query), accessor, QueryParameterSetter.ErrorHandling.LENIENT);
+ countParameterBinder.get().bind(new QueryParameterSetter.BindableQuery(query), accessor,
+ QueryParameterSetter.ErrorHandling.LENIENT);
return query;
}
diff --git a/spring-data-jpa/src/main/java/org/springframework/data/jpa/repository/query/HibernateJpaParametersParameterAccessor.java b/spring-data-jpa/src/main/java/org/springframework/data/jpa/repository/query/HibernateJpaParametersParameterAccessor.java
index 53291a0ea0..22ea109db7 100644
--- a/spring-data-jpa/src/main/java/org/springframework/data/jpa/repository/query/HibernateJpaParametersParameterAccessor.java
+++ b/spring-data-jpa/src/main/java/org/springframework/data/jpa/repository/query/HibernateJpaParametersParameterAccessor.java
@@ -51,7 +51,7 @@ class HibernateJpaParametersParameterAccessor extends JpaParametersParameterAcce
* @param values must not be {@literal null}.
* @param em must not be {@literal null}.
*/
- HibernateJpaParametersParameterAccessor(Parameters, ?> parameters, Object[] values, EntityManager em) {
+ HibernateJpaParametersParameterAccessor(JpaParameters parameters, Object[] values, EntityManager em) {
super(parameters, values);
diff --git a/spring-data-jpa/src/main/java/org/springframework/data/jpa/repository/query/JpaCountQueryCreator.java b/spring-data-jpa/src/main/java/org/springframework/data/jpa/repository/query/JpaCountQueryCreator.java
index 851a867214..455e3dd865 100644
--- a/spring-data-jpa/src/main/java/org/springframework/data/jpa/repository/query/JpaCountQueryCreator.java
+++ b/spring-data-jpa/src/main/java/org/springframework/data/jpa/repository/query/JpaCountQueryCreator.java
@@ -15,16 +15,12 @@
*/
package org.springframework.data.jpa.repository.query;
-import jakarta.persistence.criteria.CriteriaBuilder;
-import jakarta.persistence.criteria.CriteriaQuery;
-import jakarta.persistence.criteria.Expression;
-import jakarta.persistence.criteria.Predicate;
-import jakarta.persistence.criteria.Root;
+import jakarta.persistence.EntityManager;
import org.springframework.data.domain.Sort;
+import org.springframework.data.jpa.repository.support.JpqlQueryTemplates;
import org.springframework.data.repository.query.ReturnedType;
import org.springframework.data.repository.query.parser.PartTree;
-import org.springframework.lang.Nullable;
/**
* Special {@link JpaQueryCreator} that creates a count projecting query.
@@ -36,41 +32,35 @@
*/
public class JpaCountQueryCreator extends JpaQueryCreator {
- private boolean distinct;
+ private final boolean distinct;
+ private final ReturnedType returnedType;
/**
- * Creates a new {@link JpaCountQueryCreator}.
+ * Creates a new {@link JpaCountQueryCreator}
*
* @param tree
- * @param type
- * @param builder
+ * @param returnedType
* @param provider
+ * @param templates
+ * @param em
*/
- public JpaCountQueryCreator(PartTree tree, ReturnedType type, CriteriaBuilder builder,
- ParameterMetadataProvider provider) {
+ public JpaCountQueryCreator(PartTree tree, ReturnedType returnedType, ParameterMetadataProvider provider,
+ JpqlQueryTemplates templates, EntityManager em) {
- super(tree, type, builder, provider);
+ super(tree, returnedType, provider, templates, em);
this.distinct = tree.isDistinct();
+ this.returnedType = returnedType;
}
@Override
- protected CriteriaQuery extends Object> createCriteriaQuery(CriteriaBuilder builder, ReturnedType type) {
+ protected JpqlQueryBuilder.Select buildQuery(Sort sort) {
- return builder.createQuery(Long.class);
- }
-
- @Override
- @SuppressWarnings("unchecked")
- protected CriteriaQuery extends Object> complete(@Nullable Predicate predicate, Sort sort,
- CriteriaQuery extends Object> query, CriteriaBuilder builder, Root> root) {
-
- CriteriaQuery extends Object> select = query.select(getCountQuery(query, builder, root));
- return predicate == null ? select : select.where(predicate);
- }
+ JpqlQueryBuilder.SelectStep selectStep = JpqlQueryBuilder.selectFrom(returnedType.getDomainType());
+ if (this.distinct) {
+ selectStep = selectStep.distinct();
+ }
- @SuppressWarnings("rawtypes")
- private Expression getCountQuery(CriteriaQuery> query, CriteriaBuilder builder, Root> root) {
- return distinct ? builder.countDistinct(root) : builder.count(root);
+ return selectStep.count();
}
}
diff --git a/spring-data-jpa/src/main/java/org/springframework/data/jpa/repository/query/JpaKeysetScrollQueryCreator.java b/spring-data-jpa/src/main/java/org/springframework/data/jpa/repository/query/JpaKeysetScrollQueryCreator.java
index 25e7c25ca9..bf97edc7d2 100644
--- a/spring-data-jpa/src/main/java/org/springframework/data/jpa/repository/query/JpaKeysetScrollQueryCreator.java
+++ b/spring-data-jpa/src/main/java/org/springframework/data/jpa/repository/query/JpaKeysetScrollQueryCreator.java
@@ -15,18 +15,19 @@
*/
package org.springframework.data.jpa.repository.query;
-import jakarta.persistence.criteria.CriteriaBuilder;
-import jakarta.persistence.criteria.CriteriaQuery;
-import jakarta.persistence.criteria.Predicate;
-import jakarta.persistence.criteria.Root;
+import jakarta.persistence.EntityManager;
+import java.util.ArrayList;
import java.util.Collection;
import java.util.LinkedHashSet;
+import java.util.List;
import java.util.Set;
+import java.util.concurrent.atomic.AtomicInteger;
import org.springframework.data.domain.KeysetScrollPosition;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.repository.support.JpaEntityInformation;
+import org.springframework.data.jpa.repository.support.JpqlQueryTemplates;
import org.springframework.data.repository.query.ReturnedType;
import org.springframework.data.repository.query.parser.PartTree;
import org.springframework.lang.Nullable;
@@ -41,35 +42,67 @@ class JpaKeysetScrollQueryCreator extends JpaQueryCreator {
private final JpaEntityInformation, ?> entityInformation;
private final KeysetScrollPosition scrollPosition;
+ private final ParameterMetadataProvider provider;
+ private final List syntheticBindings = new ArrayList<>();
- public JpaKeysetScrollQueryCreator(PartTree tree, ReturnedType type, CriteriaBuilder builder,
- ParameterMetadataProvider provider, JpaEntityInformation, ?> entityInformation,
- KeysetScrollPosition scrollPosition) {
+ public JpaKeysetScrollQueryCreator(PartTree tree, ReturnedType type, ParameterMetadataProvider provider,
+ JpqlQueryTemplates templates, JpaEntityInformation, ?> entityInformation, KeysetScrollPosition scrollPosition,
+ EntityManager em) {
- super(tree, type, builder, provider);
+ super(tree, type, provider, templates, em);
this.entityInformation = entityInformation;
this.scrollPosition = scrollPosition;
+ this.provider = provider;
}
@Override
- protected CriteriaQuery> complete(@Nullable Predicate predicate, Sort sort, CriteriaQuery> query,
- CriteriaBuilder builder, Root> root) {
+ public List getBindings() {
+
+ List partTreeBindings = super.getBindings();
+ List bindings = new ArrayList<>(partTreeBindings.size() + this.syntheticBindings.size());
+ bindings.addAll(partTreeBindings);
+ bindings.addAll(this.syntheticBindings);
+
+ return bindings;
+ }
+
+ @Override
+ protected JpqlQueryBuilder.AbstractJpqlQuery createQuery(@Nullable JpqlQueryBuilder.Predicate predicate, Sort sort) {
KeysetScrollSpecification