Skip to content

Commit b174ebb

Browse files
committed
Refactor ParameterMetadata to PartTreeParameterBinding.
Avoid having two similar approaches while setter factories operate on ParameterBinding.
1 parent 267b640 commit b174ebb

17 files changed

+349
-311
lines changed

spring-data-jpa/src/main/java/org/springframework/data/jpa/repository/query/AbstractStringBasedJpaQuery.java

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,6 @@ abstract class AbstractStringBasedJpaQuery extends AbstractJpaQuery {
5252
private final Lazy<DeclaredQuery> countQuery;
5353
private final QueryMethodEvaluationContextProvider evaluationContextProvider;
5454
private final SpelExpressionParser parser;
55-
private final QueryParameterSetter.QueryMetadataCache metadataCache = new QueryParameterSetter.QueryMetadataCache();
5655
private final QueryRewriter queryRewriter;
5756
private final QuerySortRewriter querySortRewriter;
5857
private final Lazy<ParameterBinder> countParameterBinder;
@@ -123,11 +122,9 @@ public Query doCreateQuery(JpaParametersParameterAccessor accessor) {
123122

124123
Query query = createJpaQuery(sortedQueryString, sort, accessor.getPageable(), processor.getReturnedType());
125124

126-
QueryParameterSetter.QueryMetadata metadata = metadataCache.getMetadata(sortedQueryString, query);
127-
128125
// it is ok to reuse the binding contained in the ParameterBinder although we create a new query String because the
129126
// parameters in the query do not change.
130-
return parameterBinder.get().bindAndPrepare(query, metadata, accessor);
127+
return parameterBinder.get().bindAndPrepare(query, accessor);
131128
}
132129

133130
String getSortedQueryString(Sort sort) {
@@ -154,9 +151,8 @@ protected Query doCreateCountQuery(JpaParametersParameterAccessor accessor) {
154151
? em.createNativeQuery(queryString) //
155152
: em.createQuery(queryString, Long.class);
156153

157-
QueryParameterSetter.QueryMetadata metadata = metadataCache.getMetadata(queryString, query);
158-
159-
countParameterBinder.get().bind(metadata.withQuery(query), accessor, QueryParameterSetter.ErrorHandling.LENIENT);
154+
countParameterBinder.get().bind(new QueryParameterSetter.BindableQuery(query), accessor,
155+
QueryParameterSetter.ErrorHandling.LENIENT);
160156

161157
return query;
162158
}

spring-data-jpa/src/main/java/org/springframework/data/jpa/repository/query/JpaKeysetScrollQueryCreator.java

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ class JpaKeysetScrollQueryCreator extends JpaQueryCreator {
4343
private final JpaEntityInformation<?, ?> entityInformation;
4444
private final KeysetScrollPosition scrollPosition;
4545
private final ParameterMetadataProvider provider;
46-
private final List<ParameterBinding.Synthetic> bindings = new ArrayList<>();
46+
private final List<ParameterBinding> syntheticBindings = new ArrayList<>();
4747

4848
public JpaKeysetScrollQueryCreator(PartTree tree, ReturnedType type, ParameterMetadataProvider provider,
4949
JpqlQueryTemplates templates, JpaEntityInformation<?, ?> entityInformation, KeysetScrollPosition scrollPosition,
@@ -57,7 +57,13 @@ public JpaKeysetScrollQueryCreator(PartTree tree, ReturnedType type, ParameterMe
5757
}
5858

5959
@Override
60-
List<ParameterBinding.Synthetic> getSyntheticParameterBindings() {
60+
public List<ParameterBinding> getBindings() {
61+
62+
List<ParameterBinding> partTreeBindings = super.getBindings();
63+
List<ParameterBinding> bindings = new ArrayList<>(partTreeBindings.size() + this.syntheticBindings.size());
64+
bindings.addAll(partTreeBindings);
65+
bindings.addAll(this.syntheticBindings);
66+
6167
return bindings;
6268
}
6369

@@ -69,11 +75,11 @@ protected JpqlQueryBuilder.AbstractJpqlQuery createQuery(@Nullable JpqlQueryBuil
6975

7076
JpqlQueryBuilder.Select query = buildQuery(keysetSpec.sort());
7177

72-
AtomicInteger counter = new AtomicInteger(provider.getExpressions().size());
78+
AtomicInteger counter = new AtomicInteger(provider.getBindings().size());
7379
JpqlQueryBuilder.Predicate keysetPredicate = keysetSpec.createJpqlPredicate(getFrom(), getEntity(), value -> {
7480

75-
bindings.add(ParameterBinding.ParameterOrigin.synthetic(value));
76-
return JpqlQueryBuilder.expression(render(counter.getAndIncrement()));
81+
syntheticBindings.add(provider.nextSynthetic(value, scrollPosition));
82+
return JpqlQueryBuilder.expression(render(counter.incrementAndGet()));
7783
});
7884
JpqlQueryBuilder.Predicate predicateToUse = getPredicate(predicate, keysetPredicate);
7985

spring-data-jpa/src/main/java/org/springframework/data/jpa/repository/query/JpaQueryCreator.java

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -27,13 +27,13 @@
2727

2828
import java.util.ArrayList;
2929
import java.util.Collection;
30-
import java.util.Collections;
3130
import java.util.Iterator;
3231
import java.util.List;
3332

3433
import org.springframework.data.domain.Sort;
3534
import org.springframework.data.jpa.domain.JpaSort;
3635
import org.springframework.data.jpa.repository.query.JpqlQueryBuilder.PathAndOrigin;
36+
import org.springframework.data.jpa.repository.query.ParameterBinding.PartTreeParameterBinding;
3737
import org.springframework.data.jpa.repository.query.ParameterMetadataProvider.ParameterMetadata;
3838
import org.springframework.data.jpa.repository.support.JpqlQueryTemplates;
3939
import org.springframework.data.mapping.PropertyPath;
@@ -58,7 +58,7 @@
5858
* @author Andrey Kovalev
5959
* @author Greg Turnquist
6060
*/
61-
public class JpaQueryCreator extends AbstractQueryCreator<String, JpqlQueryBuilder.Predicate> {
61+
class JpaQueryCreator extends AbstractQueryCreator<String, JpqlQueryBuilder.Predicate> {
6262

6363
private final ReturnedType returnedType;
6464
private final ParameterMetadataProvider provider;
@@ -109,12 +109,8 @@ public boolean useTupleQuery() {
109109
*
110110
* @return the parameterExpressions
111111
*/
112-
public List<ParameterMetadata> getParameterExpressions() {
113-
return provider.getExpressions();
114-
}
115-
116-
List<ParameterBinding.Synthetic> getSyntheticParameterBindings() {
117-
return Collections.emptyList();
112+
public List<ParameterBinding> getBindings() {
113+
return provider.getBindings();
118114
}
119115

120116
@Override
@@ -254,8 +250,12 @@ Collection<String> getRequiredSelection(Sort sort, ReturnedType returnedType) {
254250
return returnedType.getInputProperties();
255251
}
256252

253+
String render(ParameterBinding binding) {
254+
return render(binding.getRequiredPosition());
255+
}
256+
257257
String render(int position) {
258-
return "?" + (position + 1);
258+
return "?" + position;
259259
}
260260

261261
private String render(ParameterMetadata metadata) {
@@ -311,8 +311,8 @@ public JpqlQueryBuilder.Predicate build() {
311311

312312
switch (type) {
313313
case BETWEEN:
314-
ParameterMetadata first = provider.next(part);
315-
ParameterMetadata second = provider.next(part);
314+
PartTreeParameterBinding first = provider.next(part);
315+
ParameterBinding second = provider.next(part);
316316
return where.between(render(first), render(second));
317317
case AFTER:
318318
case GREATER_THAN:
@@ -347,7 +347,7 @@ public JpqlQueryBuilder.Predicate build() {
347347
case LIKE:
348348
case NOT_LIKE:
349349

350-
ParameterMetadata parameter = provider.next(part, String.class);
350+
PartTreeParameterBinding parameter = provider.next(part, String.class);
351351
JpqlQueryBuilder.Expression parameterExpression = potentiallyIgnoreCase(part.getProperty(),
352352
JpqlQueryBuilder.parameter(render(parameter)));
353353
// Predicate like = builder.like(propertyExpression, parameterExpression, escape.getEscapeCharacter());
@@ -362,7 +362,7 @@ public JpqlQueryBuilder.Predicate build() {
362362
case FALSE:
363363
return where.isFalse();
364364
case SIMPLE_PROPERTY:
365-
ParameterMetadata metadata = provider.next(part);
365+
PartTreeParameterBinding metadata = provider.next(part);
366366

367367
if (metadata.isIsNullParameter()) {
368368
return where.isNull();

spring-data-jpa/src/main/java/org/springframework/data/jpa/repository/query/NamedQuery.java

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,6 @@ final class NamedQuery extends AbstractJpaQuery {
5252
private final @Nullable String countProjection;
5353
private final boolean namedCountQueryIsPresent;
5454
private final Lazy<DeclaredQuery> declaredQuery;
55-
private final QueryParameterSetter.QueryMetadataCache metadataCache;
5655

5756
/**
5857
* Creates a new {@link NamedQuery}.
@@ -93,7 +92,6 @@ private NamedQuery(JpaQueryMethod method, EntityManager em) {
9392

9493
// TODO: Detect whether a named query is a native one.
9594
this.declaredQuery = Lazy.of(() -> DeclaredQuery.of(queryString, query.toString().contains("NativeQuery")));
96-
this.metadataCache = new QueryParameterSetter.QueryMetadataCache();
9795
}
9896

9997
/**
@@ -165,9 +163,7 @@ protected Query doCreateQuery(JpaParametersParameterAccessor accessor) {
165163
? em.createNamedQuery(queryName) //
166164
: em.createNamedQuery(queryName, typeToRead);
167165

168-
QueryParameterSetter.QueryMetadata metadata = metadataCache.getMetadata(queryName, query);
169-
170-
return parameterBinder.get().bindAndPrepare(query, metadata, accessor);
166+
return parameterBinder.get().bindAndPrepare(query, accessor);
171167
}
172168

173169
@Override
@@ -188,9 +184,7 @@ protected TypedQuery<Long> doCreateCountQuery(JpaParametersParameterAccessor acc
188184
countQuery = em.createQuery(countQueryString, Long.class);
189185
}
190186

191-
QueryParameterSetter.QueryMetadata metadata = metadataCache.getMetadata(cacheKey, countQuery);
192-
193-
return parameterBinder.get().bind(countQuery, metadata, accessor);
187+
return parameterBinder.get().bind(countQuery, accessor);
194188
}
195189

196190
@Override

spring-data-jpa/src/main/java/org/springframework/data/jpa/repository/query/ParameterBinder.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -72,10 +72,10 @@ public ParameterBinder(JpaParameters parameters, Iterable<QueryParameterSetter>
7272
this.useJpaForPaging = useJpaForPaging;
7373
}
7474

75-
public <T extends Query> T bind(T jpaQuery, QueryParameterSetter.QueryMetadata metadata,
75+
public <T extends Query> T bind(T jpaQuery,
7676
JpaParametersParameterAccessor accessor) {
7777

78-
bind(metadata.withQuery(jpaQuery), accessor, ErrorHandling.STRICT);
78+
bind(new QueryParameterSetter.BindableQuery(jpaQuery), accessor, ErrorHandling.STRICT);
7979
return jpaQuery;
8080
}
8181

@@ -94,10 +94,10 @@ public void bind(QueryParameterSetter.BindableQuery query, JpaParametersParamete
9494
* @param metadata must not be {@literal null}.
9595
* @param accessor must not be {@literal null}.
9696
*/
97-
Query bindAndPrepare(Query query, QueryParameterSetter.QueryMetadata metadata,
97+
Query bindAndPrepare(Query query,
9898
JpaParametersParameterAccessor accessor) {
9999

100-
bind(query, metadata, accessor);
100+
bind(query, accessor);
101101

102102
Pageable pageable = accessor.getPageable();
103103

spring-data-jpa/src/main/java/org/springframework/data/jpa/repository/query/ParameterBinderFactory.java

Lines changed: 7 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@
2121
import org.springframework.data.jpa.repository.query.JpaParameters.JpaParameter;
2222
import org.springframework.data.jpa.repository.query.ParameterBinding.BindingIdentifier;
2323
import org.springframework.data.jpa.repository.query.ParameterBinding.ParameterOrigin;
24-
import org.springframework.data.jpa.repository.query.ParameterMetadataProvider.ParameterMetadata;
2524
import org.springframework.data.repository.query.QueryMethodEvaluationContextProvider;
2625
import org.springframework.expression.spel.standard.SpelExpressionParser;
2726
import org.springframework.util.Assert;
@@ -54,29 +53,21 @@ static ParameterBinder createBinder(JpaParameters parameters) {
5453
}
5554

5655
/**
57-
* Creates a {@link ParameterBinder} that just matches method parameter to parameters of a
58-
* {@link jakarta.persistence.criteria.CriteriaQuery}.
56+
* Creates a {@link ParameterBinder} that matches method parameter to parameters of a
57+
* {@link jakarta.persistence.Query} and that can bind synthetic parameters.
5958
*
6059
* @param parameters method parameters that are available for binding, must not be {@literal null}.
61-
* @param metadata parameter metadata for method argument parameters, must not be {@literal null}.
62-
* @param syntheticBindings additional (e.g. synthetic) syntheticBindings, must not be {@literal null}.
60+
* @param bindings parameter bindings for method argument and synthetic parameters, must not be {@literal null}.
6361
* @return a {@link ParameterBinder} that can assign values for the method parameters to query parameters of a
64-
* {@link jakarta.persistence.criteria.CriteriaQuery}
62+
* {@link jakarta.persistence.Query}
6563
*/
66-
static ParameterBinder createCriteriaBinder(JpaParameters parameters, List<ParameterMetadata> metadata,
67-
List<ParameterBinding.Synthetic> syntheticBindings) {
64+
static ParameterBinder createBinder(JpaParameters parameters, List<ParameterBinding> bindings) {
6865

6966
Assert.notNull(parameters, "JpaParameters must not be null");
70-
Assert.notNull(metadata, "Parameter metadata must not be null");
71-
72-
List<ParameterBinding> bindingsToUse = getBindings(parameters);
73-
int offset = bindingsToUse.size();
74-
for (ParameterBinding.Synthetic binding : syntheticBindings) {
75-
bindingsToUse.add(new ParameterBinding(BindingIdentifier.of(++offset), binding));
76-
}
67+
Assert.notNull(bindings, "Parameter bindings must not be null");
7768

7869
return new ParameterBinder(parameters,
79-
createSetters(bindingsToUse, QueryParameterSetterFactory.forPartTreeQuery(parameters, metadata),
70+
createSetters(bindings, QueryParameterSetterFactory.forPartTreeQuery(parameters),
8071
QueryParameterSetterFactory.forSynthetic()));
8172
}
8273

0 commit comments

Comments
 (0)