From e4b9ba8e0e409176ebecd1257627ac31a2ac1528 Mon Sep 17 00:00:00 2001 From: Oliver Gierke Date: Sat, 2 Jul 2016 08:59:19 +0200 Subject: [PATCH] DATAJPA-923 - QueryByExamplePredicateBuilder now considers match mode. We now inspect QueryByExamplePredicateBuilder.isAndMatching() to decide whether to concatenate the predicates built using and or or. Related tickets: DATACMNS-879. --- .../QueryByExamplePredicateBuilder.java | 10 +++++--- ...eryByExamplePredicateBuilderUnitTests.java | 23 ++++++++++++++++++- 2 files changed, 29 insertions(+), 4 deletions(-) diff --git a/src/main/java/org/springframework/data/jpa/convert/QueryByExamplePredicateBuilder.java b/src/main/java/org/springframework/data/jpa/convert/QueryByExamplePredicateBuilder.java index 1fa518568..914e4c6ce 100644 --- a/src/main/java/org/springframework/data/jpa/convert/QueryByExamplePredicateBuilder.java +++ b/src/main/java/org/springframework/data/jpa/convert/QueryByExamplePredicateBuilder.java @@ -52,6 +52,7 @@ import org.springframework.util.StringUtils; * * @author Christoph Strobl * @author Mark Paluch + * @author Oliver Gierke * @since 1.10 */ public class QueryByExamplePredicateBuilder { @@ -77,9 +78,10 @@ public class QueryByExamplePredicateBuilder { Assert.notNull(cb, "CriteriaBuilder must not be null!"); Assert.notNull(example, "Example must not be null!"); + ExampleMatcher matcher = example.getMatcher(); + List predicates = getPredicates("", cb, root, root.getModel(), example.getProbe(), - example.getProbeType(), new ExampleMatcherAccessor(example.getMatcher()), - new PathNode("root", null, example.getProbe())); + example.getProbeType(), new ExampleMatcherAccessor(matcher), new PathNode("root", null, example.getProbe())); if (predicates.isEmpty()) { return cb.isTrue(cb.literal(true)); @@ -89,7 +91,9 @@ public class QueryByExamplePredicateBuilder { return predicates.iterator().next(); } - return cb.and(predicates.toArray(new Predicate[predicates.size()])); + Predicate[] array = predicates.toArray(new Predicate[predicates.size()]); + + return matcher.isAllMatching() ? cb.and(array) : cb.or(array); } @SuppressWarnings({ "rawtypes", "unchecked" }) diff --git a/src/test/java/org/springframework/data/jpa/convert/QueryByExamplePredicateBuilderUnitTests.java b/src/test/java/org/springframework/data/jpa/convert/QueryByExamplePredicateBuilderUnitTests.java index 3ddf152da..e8f5f23a8 100644 --- a/src/test/java/org/springframework/data/jpa/convert/QueryByExamplePredicateBuilderUnitTests.java +++ b/src/test/java/org/springframework/data/jpa/convert/QueryByExamplePredicateBuilderUnitTests.java @@ -43,6 +43,8 @@ import org.junit.runner.RunWith; import org.mockito.Matchers; import org.mockito.Mock; import org.mockito.runners.MockitoJUnitRunner; +import org.springframework.data.domain.Example; +import org.springframework.data.domain.ExampleMatcher; import org.springframework.util.ObjectUtils; /** @@ -59,6 +61,7 @@ public class QueryByExamplePredicateBuilderUnitTests { @Mock Predicate truePredicate; @Mock Predicate dummyPredicate; @Mock Predicate listPredicate; + @Mock Predicate orPredicate; @Mock Path dummyPath; Set> personEntityAttribtues; @@ -102,7 +105,8 @@ public class QueryByExamplePredicateBuilderUnitTests { when(cb.literal(any(Boolean.class))).thenReturn(expressionMock); when(cb.isTrue(eq(expressionMock))).thenReturn(truePredicate); - when(cb.and(Matchers. anyVararg())).thenReturn(listPredicate); + when(cb.and(Matchers.anyVararg())).thenReturn(listPredicate); + when(cb.or(Matchers.anyVararg())).thenReturn(orPredicate); } /** @@ -166,6 +170,23 @@ public class QueryByExamplePredicateBuilderUnitTests { verify(cb, times(1)).equal(any(Expression.class), eq(2L)); } + /** + * @see DATAJPA-879 + */ + @Test + public void orConcatenatesPredicatesIfMatcherSpecifies() { + + Person person = new Person(); + person.firstname = "foo"; + person.age = 2L; + + Example example = of(person, ExampleMatcher.matchingAny()); + + assertThat(QueryByExamplePredicateBuilder.getPredicate(root, cb, example), equalTo(orPredicate)); + + verify(cb, times(1)).or(Matchers.anyVararg()); + } + static class Person { @Id Long id;