Skip to content

Commit 01e1fcb

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 114c1f4 commit 01e1fcb

File tree

2 files changed

+23
-7
lines changed

2 files changed

+23
-7
lines changed

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

Lines changed: 18 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 {@link #unrestricted()}, 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 {
@@ -65,7 +73,16 @@ static <T> Specification<T> not(@Nullable Specification<T> spec) {
6573
}
6674

6775
/**
68-
* Simple static factory method to create a specification matching all objects.
76+
* Simple static factory method to create a specification which does not participate in matching. The specification
77+
* returned is {@code null}-like, and is elided in all operations.
78+
*
79+
* <pre>
80+
* {@code
81+
* unrestricted().and(other) // consider only `other`
82+
* unrestricted().or(other) // consider only `other`
83+
* not(unrestricted()) // equivalent to `unrestricted()`
84+
* }
85+
* </pre>
6986
*
7087
* @param <T> the type of the {@link Root} the resulting {@literal Specification} operates on.
7188
* @return guaranteed to be not {@literal null}.

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({ "unchecked", "deprecation", "removal" })
5051
@ExtendWith(MockitoExtension.class)
@@ -209,15 +210,13 @@ void orCombinesSpecificationsInOrder() {
209210
verify(builder).or(firstPredicate, secondPredicate);
210211
}
211212

212-
@Test // GH-3849
213+
@Test // GH-3849, GH-4023
213214
void notWithNullPredicate() {
214215

215-
when(builder.disjunction()).thenReturn(mock(Predicate.class));
216+
Specification<Object> notSpec = Specification.not(Specification.unrestricted());
216217

217-
Specification<Object> notSpec = Specification.not((r, q, cb) -> null);
218-
219-
assertThat(notSpec.toPredicate(root, query, builder)).isNotNull();
220-
verify(builder).disjunction();
218+
assertThat(notSpec.toPredicate(root, query, builder)).isNull();
219+
verifyNoInteractions(builder);
221220
}
222221

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

0 commit comments

Comments
 (0)