Skip to content

Commit bfcb2ff

Browse files
committed
Unwrap nested collections in default Querydsl binding.
When binding values to collection-like paths, we now unwrap potentially double-wrapped collections as QuerydslPredicateBuilder attempts to convert the binding value to the type of the path. Our default is a contains binding for single elements. Closes #2834
1 parent 2937d62 commit bfcb2ff

File tree

3 files changed

+24
-10
lines changed

3 files changed

+24
-10
lines changed

src/main/java/org/springframework/data/querydsl/binding/QuerydslDefaultBinding.java

+10-1
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,16 @@ public Optional<Predicate> bind(Path<?> path, Collection<? extends Object> value
5959
BooleanBuilder builder = new BooleanBuilder();
6060

6161
for (Object element : value) {
62-
builder.and(((CollectionPathBase) path).contains(element));
62+
63+
if (element instanceof Collection<?> nestedCollection) {
64+
65+
for (Object nested : nestedCollection) {
66+
builder.and(((CollectionPathBase) path).contains(nested));
67+
}
68+
} else {
69+
builder.and(((CollectionPathBase) path).contains(element));
70+
}
71+
6372
}
6473

6574
return Optional.of(builder.getValue());

src/test/java/org/springframework/data/querydsl/binding/QuerydslDefaultBindingUnitTests.java

+12-2
Original file line numberDiff line numberDiff line change
@@ -22,13 +22,15 @@
2222

2323
import org.junit.jupiter.api.BeforeEach;
2424
import org.junit.jupiter.api.Test;
25-
2625
import org.springframework.data.querydsl.QUser;
2726

2827
/**
28+
* Unit tests for {@link QuerydslDefaultBinding}.
29+
*
2930
* @author Christoph Strobl
3031
* @author Oliver Gierke
3132
* @author Colin Gao
33+
* @author Mark Paluch
3234
*/
3335
class QuerydslDefaultBindingUnitTests {
3436

@@ -64,6 +66,14 @@ void shouldCreatePredicateWithContainingWhenPropertyIsCollectionLikeAndValueIsOb
6466
assertThat(predicate).hasValue(QUser.user.nickNames.contains("dragon reborn"));
6567
}
6668

69+
@Test // GH-2834
70+
void shouldUnwrapNestedCollectionsWithContainingWhenPropertyIsCollectionLike() {
71+
72+
var predicate = binding.bind(QUser.user.nickNames, Collections.singleton(Collections.singleton("dragon reborn")));
73+
74+
assertThat(predicate).hasValue(QUser.user.nickNames.contains("dragon reborn"));
75+
}
76+
6777
@Test // DATACMNS-669
6878
void shouldCreatePredicateWithInWhenPropertyIsAnObjectAndValueIsACollection() {
6979

@@ -73,7 +83,7 @@ void shouldCreatePredicateWithInWhenPropertyIsAnObjectAndValueIsACollection() {
7383
}
7484

7585
@Test
76-
void testname() {
86+
void shouldNotBindEmptyParameterCollection() {
7787
assertThat(binding.bind(QUser.user.lastname, Collections.emptySet())).isNotPresent();
7888
}
7989

src/test/java/org/springframework/data/querydsl/binding/QuerydslPredicateBuilderUnitTests.java

+2-7
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,10 @@
1919
import static org.assertj.core.api.Assumptions.*;
2020
import static org.springframework.test.util.ReflectionTestUtils.*;
2121

22-
import java.util.Arrays;
2322
import java.util.List;
2423

2524
import org.junit.jupiter.api.BeforeEach;
2625
import org.junit.jupiter.api.Test;
27-
2826
import org.springframework.data.querydsl.Address;
2927
import org.springframework.data.querydsl.QSpecialUser;
3028
import org.springframework.data.querydsl.QUser;
@@ -189,9 +187,7 @@ void resolvesCommaSeparatedArgumentToListCorrectly() {
189187

190188
var predicate = builder.getPredicate(USER_TYPE, values, DEFAULT_BINDINGS);
191189

192-
var constant = (Constant<Object>) ((List<?>) getField(getField(predicate, "mixin"), "args")).get(0);
193-
194-
assertThat(constant.getConstant()).isEqualTo(Arrays.asList("Walt", "Heisenberg"));
190+
assertThat(predicate).hasToString("Walt in user.nickNames && Heisenberg in user.nickNames");
195191
}
196192

197193
@Test // GH-2649
@@ -200,9 +196,8 @@ void resolvesCommaSeparatedArgumentToListCorrectlyForNestedPath() {
200196
values.add("user.nickNames", "Walt,Heisenberg");
201197

202198
var predicate = builder.getPredicate(TypeInformation.of(UserWrapper.class), values, DEFAULT_BINDINGS);
203-
var constant = (Constant<Object>) ((List<?>) getField(getField(predicate, "mixin"), "args")).get(0);
204199

205-
assertThat(constant.getConstant()).isEqualTo(Arrays.asList("Walt", "Heisenberg"));
200+
assertThat(predicate).hasToString("Walt in userWrapper.user.nickNames && Heisenberg in userWrapper.user.nickNames");
206201
}
207202

208203
@Test // DATACMNS-883

0 commit comments

Comments
 (0)