Skip to content

Commit a9279c7

Browse files
committed
Register individual bindings for IN bindings if parameter is already bound differently.
We now register a new parameter binding if the named/positional parameter is already bound in an incompatible style. Closes #3126
1 parent 50de4d7 commit a9279c7

File tree

2 files changed

+39
-22
lines changed

2 files changed

+39
-22
lines changed

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

Lines changed: 9 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -288,36 +288,28 @@ private String parseParameterBindingsOfQueryIntoBindingsAndReturnCleanedQuery(St
288288
: ParameterOrigin.ofExpression(expression);
289289

290290
BindingIdentifier targetBinding = queryParameter;
291+
Function<BindingIdentifier, ParameterBinding> bindingFactory;
291292
switch (ParameterBindingType.of(typeSource)) {
292293

293294
case LIKE:
294295

295296
Type likeType = LikeParameterBinding.getLikeTypeFrom(matcher.group(2));
296-
297-
if (origin.isExpression()) {
298-
parameterBindings.register(new LikeParameterBinding(queryParameter, origin, likeType));
299-
} else {
300-
targetBinding = parameterBindings.register(queryParameter, origin,
301-
(identifier) -> new LikeParameterBinding(identifier, origin, likeType));
302-
}
303-
297+
bindingFactory = (identifier) -> new LikeParameterBinding(identifier, origin, likeType);
304298
break;
305299

306300
case IN:
307-
308-
parameterBindings.register(new InParameterBinding(queryParameter, origin));
309-
301+
bindingFactory = (identifier) -> new InParameterBinding(identifier, origin);
310302
break;
311303

312304
case AS_IS: // fall-through we don't need a special parameter queryParameter for the given parameter.
313305
default:
306+
bindingFactory = (identifier) -> new ParameterBinding(identifier, origin);
307+
}
314308

315-
if (origin.isExpression()) {
316-
parameterBindings.register(new ParameterBinding(queryParameter, origin));
317-
} else {
318-
targetBinding = parameterBindings.register(queryParameter, origin,
319-
(identifier) -> new ParameterBinding(identifier, origin));
320-
}
309+
if (origin.isExpression()) {
310+
parameterBindings.register(bindingFactory.apply(queryParameter));
311+
} else {
312+
targetBinding = parameterBindings.register(queryParameter, origin, bindingFactory);
321313
}
322314

323315
replacement = targetBinding.hasName() ? ":" + targetBinding.getName()

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

Lines changed: 30 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -246,8 +246,6 @@ void detectsNamedInParameterBindings() {
246246
assertThat(bindings).hasSize(1);
247247

248248
assertNamedBinding(InParameterBinding.class, "ids", bindings.get(0));
249-
250-
softly.assertAll();
251249
}
252250

253251
@Test // DATAJPA-461
@@ -282,8 +280,37 @@ void detectsPositionalInParameterBindings() {
282280
assertThat(bindings).hasSize(1);
283281

284282
assertPositionalBinding(InParameterBinding.class, 1, bindings.get(0));
283+
}
285284

286-
softly.assertAll();
285+
@Test // GH-3126
286+
void allowsReuseOfParameterWithInAndRegularBinding() {
287+
288+
StringQuery query = new StringQuery(
289+
"select u from User u where COALESCE(?1) is null OR u.id in ?1 OR COALESCE(?1) is null OR u.id in ?1", true);
290+
291+
assertThat(query.hasParameterBindings()).isTrue();
292+
assertThat(query.getQueryString()).isEqualTo(
293+
"select u from User u where COALESCE(?1) is null OR u.id in ?2 OR COALESCE(?1) is null OR u.id in ?2");
294+
295+
List<ParameterBinding> bindings = query.getParameterBindings();
296+
assertThat(bindings).hasSize(2);
297+
298+
assertPositionalBinding(ParameterBinding.class, 1, bindings.get(0));
299+
assertPositionalBinding(InParameterBinding.class, 2, bindings.get(1));
300+
301+
query = new StringQuery(
302+
"select u from User u where COALESCE(:foo) is null OR u.id in :foo OR COALESCE(:foo) is null OR u.id in :foo",
303+
true);
304+
305+
assertThat(query.hasParameterBindings()).isTrue();
306+
assertThat(query.getQueryString()).isEqualTo(
307+
"select u from User u where COALESCE(:foo) is null OR u.id in :foo_1 OR COALESCE(:foo) is null OR u.id in :foo_1");
308+
309+
bindings = query.getParameterBindings();
310+
assertThat(bindings).hasSize(2);
311+
312+
assertNamedBinding(ParameterBinding.class, "foo", bindings.get(0));
313+
assertNamedBinding(InParameterBinding.class, "foo_1", bindings.get(1));
287314
}
288315

289316
@Test // DATAJPA-461
@@ -360,8 +387,6 @@ void detectsInBindingWithSpecialFrenchCharactersInParentheses() {
360387

361388
assertThat(bindings).hasSize(1);
362389
assertNamedBinding(InParameterBinding.class, "abonnés", bindings.get(0));
363-
364-
softly.assertAll();
365390
}
366391

367392
@Test // DATAJPA-545

0 commit comments

Comments
 (0)