Skip to content

Commit 6ed95e2

Browse files
peteraishermp911de
authored andcommitted
Constistent unrestricted() behaviour for all *Specification types.
Closes #4203 Original pull request: #4024 Signed-off-by: Peter Aisher <[email protected]>
1 parent c8fa55d commit 6ed95e2

File tree

2 files changed

+14
-7
lines changed

2 files changed

+14
-7
lines changed

spring-data-jpa/src/main/java/org/springframework/data/jpa/domain/Specification.java

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,13 @@
2929

3030
/**
3131
* Specification in the sense of Domain Driven Design.
32+
* <p>
33+
* Specifications can be composed into higher order functions from other specifications using
34+
* {@link #and(Specification)}, {@link #or(Specification)} or factory methods such as {@link #allOf(Iterable)}.
35+
* <p>
36+
* Composition considers whether one or more specifications contribute to the overall predicate by returning a
37+
* {@link Predicate} or {@literal null}. Specifications returning {@literal null}, such as {@code where(null)}, are
38+
* considered to not contribute to the overall predicate, and their result is not considered in the final predicate.
3239
*
3340
* @author Oliver Gierke
3441
* @author Thomas Darimont
@@ -38,6 +45,7 @@
3845
* @author Jens Schauder
3946
* @author Daniel Shuy
4047
* @author Sergey Rukin
48+
* @author Peter Aisher
4149
*/
4250
@FunctionalInterface
4351
public interface Specification<T> extends Serializable {
@@ -59,7 +67,7 @@ static <T> Specification<T> not(@Nullable Specification<T> spec) {
5967
: (root, query, builder) -> {
6068

6169
Predicate predicate = spec.toPredicate(root, query, builder);
62-
return predicate != null ? builder.not(predicate) : builder.disjunction();
70+
return predicate != null ? builder.not(predicate) : null;
6371
};
6472
}
6573

spring-data-jpa/src/test/java/org/springframework/data/jpa/domain/SpecificationUnitTests.java

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@
4545
* @author Jens Schauder
4646
* @author Mark Paluch
4747
* @author Daniel Shuy
48+
* @author Peter Aisher
4849
*/
4950
@SuppressWarnings("removal")
5051
@ExtendWith(MockitoExtension.class)
@@ -213,15 +214,13 @@ void orCombinesSpecificationsInOrder() {
213214
verify(builder).or(firstPredicate, secondPredicate);
214215
}
215216

216-
@Test // GH-3849
217+
@Test // GH-3849, GH-4023
217218
void notWithNullPredicate() {
218219

219-
when(builder.disjunction()).thenReturn(mock(Predicate.class));
220+
Specification<Object> notSpec = Specification.not(Specification.unrestricted());
220221

221-
Specification<Object> notSpec = Specification.not((r, q, cb) -> null);
222-
223-
assertThat(notSpec.toPredicate(root, query, builder)).isNotNull();
224-
verify(builder).disjunction();
222+
assertThat(notSpec.toPredicate(root, query, builder)).isNull();
223+
verifyNoInteractions(builder);
225224
}
226225

227226
static class SerializableSpecification implements Serializable, Specification<Object> {

0 commit comments

Comments
 (0)