Skip to content

Commit 238d679

Browse files
committed
Fix positional binding when only later positions are reported
Signed-off-by: Shigeru Hagiwara <shigeru.hagiwara@ofaas.jp>
1 parent c5addc7 commit 238d679

File tree

2 files changed

+52
-5
lines changed

2 files changed

+52
-5
lines changed

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

Lines changed: 28 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -109,10 +109,12 @@ private void setParameter(BindableQuery query, Object value, ErrorHandler errorH
109109
} else {
110110

111111
Integer position = parameter.getPosition();
112+
boolean canBindByPosition = query.hasPositionParameters()
113+
? query.hasParameterPosition(position) || errorHandler == LENIENT || errorHandler == STRICT
114+
: query.getParameters().size() >= position || errorHandler == LENIENT;
112115

113116
if (position != null //
114-
&& (query.getParameters().size() >= position //
115-
|| errorHandler == LENIENT //
117+
&& (canBindByPosition //
116118
|| query.registerExcessParameters())) {
117119
query.setParameter(position, value);
118120
}
@@ -163,11 +165,13 @@ private void setParameter(BindableQuery query, Date date, ErrorHandler errorHand
163165
} else {
164166

165167
Integer position = parameter.getPosition();
168+
boolean canBindByPosition = query.hasPositionParameters()
169+
? query.hasParameterPosition(position) || errorHandler == LENIENT || errorHandler == STRICT
170+
: query.getParameters().size() >= position || errorHandler == LENIENT;
166171

167172
if (position != null //
168-
&& (query.getParameters().size() >= parameter.getPosition() //
169-
|| query.registerExcessParameters() //
170-
|| errorHandler == LENIENT)) {
173+
&& (canBindByPosition //
174+
|| query.registerExcessParameters())) {
171175

172176
query.setParameter(parameter.getPosition(), date, temporalType);
173177
}
@@ -242,6 +246,25 @@ public boolean registerExcessParameters() {
242246
return this.registerExcessParameters;
243247
}
244248

249+
boolean hasPositionParameters() {
250+
for (Parameter<?> candidate : parameters) {
251+
if (candidate.getPosition() != null) {
252+
return true;
253+
}
254+
}
255+
return false;
256+
}
257+
258+
boolean hasParameterPosition(int position) {
259+
for (Parameter<?> candidate : parameters) {
260+
Integer candidatePosition = candidate.getPosition();
261+
if (candidatePosition != null && candidatePosition == position) {
262+
return true;
263+
}
264+
}
265+
return false;
266+
}
267+
245268
/**
246269
* Returns the actual target {@link Query} instance, even if the provided query is a {@link Proxy} based on
247270
* {@link org.springframework.orm.jpa.SharedEntityManagerCreator.DeferredQueryInvocationHandler}.

spring-data-jpa/src/test/java/org/springframework/data/jpa/repository/query/NamedOrIndexedQueryParameterSetterUnitTests.java

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,30 @@ void lenientSetsParameterWhenSuccessIsUnsure() {
162162

163163
}
164164

165+
@Test // DATAJPA-4167
166+
void setsParameterWhenQueryExposesOnlySecondPosition() {
167+
168+
Query query = mock(Query.class);
169+
doReturn(Collections.singleton(new ParameterImpl(null, 2))).when(query).getParameters();
170+
171+
for (TemporalType temporalType : temporalTypes) {
172+
173+
QueryParameterSetter setter = QueryParameterSetter.create( //
174+
firstValueExtractor, //
175+
new ParameterImpl(null, 2), //
176+
temporalType //
177+
);
178+
179+
setter.setParameter(QueryParameterSetter.BindableQuery.from(query), methodArguments, STRICT);
180+
181+
if (temporalType == null) {
182+
verify(query).setParameter(eq(2), any(Date.class));
183+
} else {
184+
verify(query).setParameter(eq(2), any(Date.class), eq(temporalType));
185+
}
186+
}
187+
}
188+
165189
/**
166190
* This scenario happens when the only (name) parameter is part of an ORDER BY clause and gets stripped of for the
167191
* count query. Then the count query has no named parameter but the parameter provided has a {@literal null} position.

0 commit comments

Comments
 (0)