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
This commit is contained in:
@@ -59,7 +59,16 @@ class QuerydslDefaultBinding implements MultiValueBinding<Path<? extends Object>
|
|||||||
BooleanBuilder builder = new BooleanBuilder();
|
BooleanBuilder builder = new BooleanBuilder();
|
||||||
|
|
||||||
for (Object element : value) {
|
for (Object element : value) {
|
||||||
builder.and(((CollectionPathBase) path).contains(element));
|
|
||||||
|
if (element instanceof Collection<?> nestedCollection) {
|
||||||
|
|
||||||
|
for (Object nested : nestedCollection) {
|
||||||
|
builder.and(((CollectionPathBase) path).contains(nested));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
builder.and(((CollectionPathBase) path).contains(element));
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return Optional.of(builder.getValue());
|
return Optional.of(builder.getValue());
|
||||||
|
|||||||
@@ -22,13 +22,15 @@ import java.util.Collections;
|
|||||||
|
|
||||||
import org.junit.jupiter.api.BeforeEach;
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
import org.springframework.data.querydsl.QUser;
|
import org.springframework.data.querydsl.QUser;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Unit tests for {@link QuerydslDefaultBinding}.
|
||||||
|
*
|
||||||
* @author Christoph Strobl
|
* @author Christoph Strobl
|
||||||
* @author Oliver Gierke
|
* @author Oliver Gierke
|
||||||
* @author Colin Gao
|
* @author Colin Gao
|
||||||
|
* @author Mark Paluch
|
||||||
*/
|
*/
|
||||||
class QuerydslDefaultBindingUnitTests {
|
class QuerydslDefaultBindingUnitTests {
|
||||||
|
|
||||||
@@ -64,6 +66,14 @@ class QuerydslDefaultBindingUnitTests {
|
|||||||
assertThat(predicate).hasValue(QUser.user.nickNames.contains("dragon reborn"));
|
assertThat(predicate).hasValue(QUser.user.nickNames.contains("dragon reborn"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test // GH-2834
|
||||||
|
void shouldUnwrapNestedCollectionsWithContainingWhenPropertyIsCollectionLike() {
|
||||||
|
|
||||||
|
var predicate = binding.bind(QUser.user.nickNames, Collections.singleton(Collections.singleton("dragon reborn")));
|
||||||
|
|
||||||
|
assertThat(predicate).hasValue(QUser.user.nickNames.contains("dragon reborn"));
|
||||||
|
}
|
||||||
|
|
||||||
@Test // DATACMNS-669
|
@Test // DATACMNS-669
|
||||||
void shouldCreatePredicateWithInWhenPropertyIsAnObjectAndValueIsACollection() {
|
void shouldCreatePredicateWithInWhenPropertyIsAnObjectAndValueIsACollection() {
|
||||||
|
|
||||||
@@ -73,7 +83,7 @@ class QuerydslDefaultBindingUnitTests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void testname() {
|
void shouldNotBindEmptyParameterCollection() {
|
||||||
assertThat(binding.bind(QUser.user.lastname, Collections.emptySet())).isNotPresent();
|
assertThat(binding.bind(QUser.user.lastname, Collections.emptySet())).isNotPresent();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -19,12 +19,10 @@ import static org.assertj.core.api.Assertions.*;
|
|||||||
import static org.assertj.core.api.Assumptions.*;
|
import static org.assertj.core.api.Assumptions.*;
|
||||||
import static org.springframework.test.util.ReflectionTestUtils.*;
|
import static org.springframework.test.util.ReflectionTestUtils.*;
|
||||||
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import org.junit.jupiter.api.BeforeEach;
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
import org.springframework.data.querydsl.Address;
|
import org.springframework.data.querydsl.Address;
|
||||||
import org.springframework.data.querydsl.QSpecialUser;
|
import org.springframework.data.querydsl.QSpecialUser;
|
||||||
import org.springframework.data.querydsl.QUser;
|
import org.springframework.data.querydsl.QUser;
|
||||||
@@ -189,9 +187,7 @@ class QuerydslPredicateBuilderUnitTests {
|
|||||||
|
|
||||||
var predicate = builder.getPredicate(USER_TYPE, values, DEFAULT_BINDINGS);
|
var predicate = builder.getPredicate(USER_TYPE, values, DEFAULT_BINDINGS);
|
||||||
|
|
||||||
var constant = (Constant<Object>) ((List<?>) getField(getField(predicate, "mixin"), "args")).get(0);
|
assertThat(predicate).hasToString("Walt in user.nickNames && Heisenberg in user.nickNames");
|
||||||
|
|
||||||
assertThat(constant.getConstant()).isEqualTo(Arrays.asList("Walt", "Heisenberg"));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test // GH-2649
|
@Test // GH-2649
|
||||||
@@ -200,9 +196,8 @@ class QuerydslPredicateBuilderUnitTests {
|
|||||||
values.add("user.nickNames", "Walt,Heisenberg");
|
values.add("user.nickNames", "Walt,Heisenberg");
|
||||||
|
|
||||||
var predicate = builder.getPredicate(TypeInformation.of(UserWrapper.class), values, DEFAULT_BINDINGS);
|
var predicate = builder.getPredicate(TypeInformation.of(UserWrapper.class), values, DEFAULT_BINDINGS);
|
||||||
var constant = (Constant<Object>) ((List<?>) getField(getField(predicate, "mixin"), "args")).get(0);
|
|
||||||
|
|
||||||
assertThat(constant.getConstant()).isEqualTo(Arrays.asList("Walt", "Heisenberg"));
|
assertThat(predicate).hasToString("Walt in userWrapper.user.nickNames && Heisenberg in userWrapper.user.nickNames");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test // DATACMNS-883
|
@Test // DATACMNS-883
|
||||||
|
|||||||
Reference in New Issue
Block a user