Skip to content

Commit d6579c7

Browse files
committed
Polishing.
1 parent a7b737b commit d6579c7

File tree

6 files changed

+69
-45
lines changed

6 files changed

+69
-45
lines changed

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

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,10 @@
1717

1818
import jakarta.persistence.EntityManager;
1919

20+
import java.util.ArrayList;
2021
import java.util.Collection;
2122
import java.util.LinkedHashSet;
23+
import java.util.List;
2224
import java.util.Set;
2325

2426
import org.springframework.data.domain.KeysetScrollPosition;
@@ -40,6 +42,7 @@ class JpaKeysetScrollQueryCreator extends JpaQueryCreator {
4042
private final JpaEntityInformation<?, ?> entityInformation;
4143
private final KeysetScrollPosition scrollPosition;
4244
private final ParameterMetadataProvider provider;
45+
private final List<ParameterBinding> bindings = new ArrayList<>();
4346

4447
public JpaKeysetScrollQueryCreator(PartTree tree, ReturnedType type, ParameterMetadataProvider provider,
4548
JpqlQueryTemplates templates, JpaEntityInformation<?, ?> entityInformation, KeysetScrollPosition scrollPosition,
@@ -52,13 +55,23 @@ public JpaKeysetScrollQueryCreator(PartTree tree, ReturnedType type, ParameterMe
5255
this.provider = provider;
5356
}
5457

58+
@Override
59+
List<ParameterBinding> getParameterBindings() {
60+
return bindings;
61+
}
62+
5563
@Override
5664
protected JpqlQueryBuilder.AbstractJpqlQuery createQuery(@Nullable JpqlQueryBuilder.Predicate predicate, Sort sort) {
5765

5866
KeysetScrollSpecification<Object> keysetSpec = new KeysetScrollSpecification<>(scrollPosition, sort,
5967
entityInformation);
6068
JpqlQueryBuilder.Predicate keysetPredicate = keysetSpec.createJpqlPredicate(getFrom(), getEntity(), value -> {
61-
return JpqlQueryBuilder.expression(render(provider.synthetic(value)));
69+
70+
int position = provider.nextPosition();
71+
bindings.add(new ParameterBinding(ParameterBinding.BindingIdentifier.of(position + 1),
72+
ParameterBinding.ParameterOrigin.synthetic(value)));
73+
74+
return JpqlQueryBuilder.expression(render(position));
6275
});
6376

6477
JpqlQueryBuilder.Select query = buildQuery(keysetSpec.sort());

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

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
import jakarta.persistence.metamodel.SingularAttribute;
2828

2929
import java.util.Collection;
30+
import java.util.Collections;
3031
import java.util.Iterator;
3132
import java.util.List;
3233

@@ -108,6 +109,10 @@ public List<ParameterMetadata<?>> getParameterExpressions() {
108109
return provider.getExpressions();
109110
}
110111

112+
List<ParameterBinding> getParameterBindings() {
113+
return Collections.emptyList();
114+
}
115+
111116
@Override
112117
protected JpqlQueryBuilder.Predicate create(Part part, Iterator<Object> iterator) {
113118
return toPredicate(part);
@@ -233,8 +238,12 @@ Collection<String> getRequiredSelection(Sort sort, ReturnedType returnedType) {
233238
return returnedType.getInputProperties();
234239
}
235240

236-
String render(ParameterMetadata<?> metadata) {
237-
return "?" + (metadata.getPosition() + 1);
241+
String render(int position) {
242+
return "?" + (position + 1);
243+
}
244+
245+
private String render(ParameterMetadata<?> metadata) {
246+
return render(metadata.getPosition());
238247
}
239248

240249
/**

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

Lines changed: 10 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -58,29 +58,23 @@ static ParameterBinder createBinder(JpaParameters parameters) {
5858
* {@link jakarta.persistence.criteria.CriteriaQuery}.
5959
*
6060
* @param parameters method parameters that are available for binding, must not be {@literal null}.
61-
* @param metadata must not be {@literal null}.
61+
* @param metadata parameter metadata for method argument parameters, must not be {@literal null}.
62+
* @param bindings additional (e.g. synthetic) bindings, must not be {@literal null}.
6263
* @return a {@link ParameterBinder} that can assign values for the method parameters to query parameters of a
6364
* {@link jakarta.persistence.criteria.CriteriaQuery}
6465
*/
65-
static ParameterBinder createCriteriaBinder(JpaParameters parameters, List<ParameterMetadata<?>> metadata) {
66+
static ParameterBinder createCriteriaBinder(JpaParameters parameters, List<ParameterMetadata<?>> metadata,
67+
List<ParameterBinding> bindings) {
6668

6769
Assert.notNull(parameters, "JpaParameters must not be null");
6870
Assert.notNull(metadata, "Parameter metadata must not be null");
6971

70-
QueryParameterSetterFactory setterFactory = QueryParameterSetterFactory.forPartTreeQuery(parameters, metadata);
71-
List<ParameterBinding> bindings = getBindings(parameters);
72-
73-
if (metadata.size() > parameters.getNumberOfParameters()) {
74-
for (int i = parameters.getNumberOfParameters() - 1; i < metadata.size(); i++) {
75-
76-
ParameterMetadata<?> meta = metadata.get(i);
77-
ParameterBinding binding = new ParameterBinding(BindingIdentifier.of(meta.getPosition() + 1),
78-
ParameterOrigin.synthetic(meta.getValue()));
79-
bindings.add(binding);
80-
}
81-
}
72+
List<ParameterBinding> bindingsToUse = getBindings(parameters);
73+
bindingsToUse.addAll(bindings);
8274

83-
return new ParameterBinder(parameters, createSetters(bindings, setterFactory));
75+
return new ParameterBinder(parameters,
76+
createSetters(bindingsToUse, QueryParameterSetterFactory.forPartTreeQuery(parameters, metadata),
77+
QueryParameterSetterFactory.forSynthetic()));
8478
}
8579

8680
/**
@@ -113,7 +107,7 @@ static ParameterBinder createQueryAwareBinder(JpaParameters parameters, Declared
113107
!query.usesPaging());
114108
}
115109

116-
private static List<ParameterBinding> getBindings(JpaParameters parameters) {
110+
static List<ParameterBinding> getBindings(JpaParameters parameters) {
117111

118112
List<ParameterBinding> result = new ArrayList<>();
119113
int bindableParameterIndex = 0;

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

Lines changed: 2 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -181,20 +181,8 @@ private <T> ParameterMetadata<T> next(Part part, Class<T> type, Parameter parame
181181
return metadata;
182182
}
183183

184-
/**
185-
* Create synthetic parameter metadata for a captured value.
186-
*
187-
* @param value
188-
* @return
189-
*/
190-
public ParameterMetadata<?> synthetic(Object value) {
191-
192-
int currentPosition = position++;
193-
ParameterMetadata<?> metadata = new ParameterMetadata<>(value, Type.SIMPLE_PROPERTY, currentPosition, templates,
194-
escape, false, false);
195-
expressions.add(metadata);
196-
197-
return metadata;
184+
public int nextPosition() {
185+
return position++;
198186
}
199187

200188
EscapeCharacter getEscape() {

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -232,7 +232,8 @@ public Query createQuery(JpaParametersParameterAccessor accessor) {
232232
}
233233

234234
List<ParameterMetadataProvider.ParameterMetadata<?>> expressions = creator.getParameterExpressions();
235-
ParameterBinder binder = ParameterBinderFactory.createCriteriaBinder(parameters, expressions);
235+
ParameterBinder binder = ParameterBinderFactory.createCriteriaBinder(parameters, expressions,
236+
creator.getParameterBindings());
236237

237238
ScrollPosition scrollPosition = accessor.getParameters().hasScrollPositionParameter()
238239
? accessor.getScrollPosition()

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

Lines changed: 30 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,10 @@ static QueryParameterSetterFactory forPartTreeQuery(JpaParameters parameters, Li
7979
return new PartTreeQueryParameterSetterFactory(parameters, metadata);
8080
}
8181

82+
static QueryParameterSetterFactory forSynthetic() {
83+
return new SyntheticParameterSetterFactory();
84+
}
85+
8286
/**
8387
* Creates a new {@link QueryParameterSetterFactory} for the given {@link SpelExpressionParser},
8488
* {@link EvaluationContextProvider} and {@link Parameters}.
@@ -211,6 +215,25 @@ private Object evaluateExpression(Expression expression, JpaParametersParameterA
211215
}
212216
}
213217

218+
/**
219+
* Handles synthetic bindings that have been captured during parameter augmenting.
220+
*
221+
* @author Mark Paluch
222+
* @since 4.0
223+
*/
224+
private static class SyntheticParameterSetterFactory extends QueryParameterSetterFactory {
225+
226+
@Override
227+
public QueryParameterSetter create(ParameterBinding binding, DeclaredQuery declaredQuery) {
228+
229+
if (!(binding.getOrigin() instanceof ParameterBinding.Synthetic s)) {
230+
return null;
231+
}
232+
233+
return createSetter(values -> s.value(), binding, null);
234+
}
235+
}
236+
214237
/**
215238
* Extracts values for parameter bindings from method parameters. It handles named as well as indexed parameters.
216239
*
@@ -258,9 +281,7 @@ public QueryParameterSetter create(ParameterBinding binding, DeclaredQuery decla
258281

259282
@Nullable
260283
private Object getValue(JpaParametersParameterAccessor accessor, Parameter parameter) {
261-
Object value = accessor.getValue(parameter);
262-
263-
return value;
284+
return accessor.getValue(parameter);
264285
}
265286
}
266287

@@ -293,6 +314,10 @@ private static class PartTreeQueryParameterSetterFactory extends QueryParameterS
293314
@Override
294315
public QueryParameterSetter create(ParameterBinding binding, DeclaredQuery declaredQuery) {
295316

317+
if (binding.getOrigin() instanceof ParameterBinding.Synthetic) {
318+
return null;
319+
}
320+
296321
int parameterIndex = binding.getRequiredPosition() - 1;
297322

298323
Assert.isTrue( //
@@ -310,15 +335,9 @@ public QueryParameterSetter create(ParameterBinding binding, DeclaredQuery decla
310335
return QueryParameterSetter.NOOP;
311336
}
312337

313-
if (binding.getOrigin() instanceof ParameterBinding.Synthetic syntheticValue) {
314-
return createSetter(values -> syntheticValue.value(), binding, null);
315-
}
316-
317338
JpaParameter parameter = parameters.getBindableParameter(parameterIndex);
318-
TemporalType temporalType = parameter.isTemporalParameter() ? parameter.getRequiredTemporalType() : null;
319-
320-
return new NamedOrIndexedQueryParameterSetter(values -> getAndPrepare(parameter, metadata, values),
321-
ParameterImpl.of(parameter, binding), temporalType);
339+
return QueryParameterSetterFactory.createSetter(values -> getAndPrepare(parameter, metadata, values), binding,
340+
parameter);
322341
}
323342

324343
@Nullable

0 commit comments

Comments
 (0)