diff --git a/spring-data-jpa/src/main/java/org/springframework/data/jpa/domain/DeleteSpecification.java b/spring-data-jpa/src/main/java/org/springframework/data/jpa/domain/DeleteSpecification.java
index 310ed0c6da..3337ae5fb1 100644
--- a/spring-data-jpa/src/main/java/org/springframework/data/jpa/domain/DeleteSpecification.java
+++ b/spring-data-jpa/src/main/java/org/springframework/data/jpa/domain/DeleteSpecification.java
@@ -31,6 +31,12 @@
/**
* Specification in the sense of Domain Driven Design to handle Criteria Deletes.
+ *
+ * Specifications can be composed into higher order functions from other specifications using
+ * {@link #and(DeleteSpecification)}, {@link #or(DeleteSpecification)} or factory methods such as
+ * {@link #allOf(Iterable)}. Composition considers whether one or more specifications contribute to the overall
+ * predicate by returning a {@link Predicate} or {@literal null}. Specifications returning {@literal null} are
+ * considered to not contribute to the overall predicate and their result is not considered in the final predicate.
*
* @author Mark Paluch
* @since 4.0
@@ -44,7 +50,7 @@ public interface DeleteSpecification extends Serializable {
* @param the type of the {@link Root} the resulting {@literal DeleteSpecification} operates on.
* @return guaranteed to be not {@literal null}.
*/
- static DeleteSpecification all() {
+ static DeleteSpecification unrestricted() {
return (root, query, builder) -> null;
}
@@ -150,13 +156,14 @@ static DeleteSpecification not(DeleteSpecification spec) {
return (root, delete, builder) -> {
- Predicate not = spec.toPredicate(root, delete, builder);
- return not != null ? builder.not(not) : null;
+ Predicate predicate = spec.toPredicate(root, delete, builder);
+ return predicate != null ? builder.not(predicate) : null;
};
}
/**
- * Applies an AND operation to all the given {@link DeleteSpecification}s.
+ * Applies an AND operation to all the given {@link DeleteSpecification}s. If {@code specifications} is empty, the
+ * resulting {@link DeleteSpecification} will be unrestricted applying to all objects.
*
* @param specifications the {@link DeleteSpecification}s to compose.
* @return the conjunction of the specifications.
@@ -169,7 +176,8 @@ static DeleteSpecification allOf(DeleteSpecification... specifications
}
/**
- * Applies an AND operation to all the given {@link DeleteSpecification}s.
+ * Applies an AND operation to all the given {@link DeleteSpecification}s. If {@code specifications} is empty, the
+ * resulting {@link DeleteSpecification} will be unrestricted applying to all objects.
*
* @param specifications the {@link DeleteSpecification}s to compose.
* @return the conjunction of the specifications.
@@ -179,11 +187,12 @@ static DeleteSpecification allOf(DeleteSpecification... specifications
static DeleteSpecification allOf(Iterable> specifications) {
return StreamSupport.stream(specifications.spliterator(), false) //
- .reduce(DeleteSpecification.all(), DeleteSpecification::and);
+ .reduce(DeleteSpecification.unrestricted(), DeleteSpecification::and);
}
/**
- * Applies an OR operation to all the given {@link DeleteSpecification}s.
+ * Applies an OR operation to all the given {@link DeleteSpecification}s. If {@code specifications} is empty, the
+ * resulting {@link DeleteSpecification} will be unrestricted applying to all objects.
*
* @param specifications the {@link DeleteSpecification}s to compose.
* @return the disjunction of the specifications.
@@ -196,7 +205,8 @@ static DeleteSpecification anyOf(DeleteSpecification... specifications
}
/**
- * Applies an OR operation to all the given {@link DeleteSpecification}s.
+ * Applies an OR operation to all the given {@link DeleteSpecification}s. If {@code specifications} is empty, the
+ * resulting {@link DeleteSpecification} will be unrestricted applying to all objects.
*
* @param specifications the {@link DeleteSpecification}s to compose.
* @return the disjunction of the specifications.
@@ -206,7 +216,7 @@ static DeleteSpecification anyOf(DeleteSpecification... specifications
static DeleteSpecification anyOf(Iterable> specifications) {
return StreamSupport.stream(specifications.spliterator(), false) //
- .reduce(DeleteSpecification.all(), DeleteSpecification::or);
+ .reduce(DeleteSpecification.unrestricted(), DeleteSpecification::or);
}
/**
diff --git a/spring-data-jpa/src/main/java/org/springframework/data/jpa/domain/PredicateSpecification.java b/spring-data-jpa/src/main/java/org/springframework/data/jpa/domain/PredicateSpecification.java
index f237715bc0..dc17edbfc4 100644
--- a/spring-data-jpa/src/main/java/org/springframework/data/jpa/domain/PredicateSpecification.java
+++ b/spring-data-jpa/src/main/java/org/springframework/data/jpa/domain/PredicateSpecification.java
@@ -30,6 +30,12 @@
/**
* Specification in the sense of Domain Driven Design.
+ *
+ * Specifications can be composed into higher order functions from other specifications using
+ * {@link #and(PredicateSpecification)}, {@link #or(PredicateSpecification)} or factory methods such as
+ * {@link #allOf(Iterable)}. Composition considers whether one or more specifications contribute to the overall
+ * predicate by returning a {@link Predicate} or {@literal null}. Specifications returning {@literal null} are
+ * considered to not contribute to the overall predicate and their result is not considered in the final predicate.
*
* @author Mark Paluch
* @since 4.0
@@ -42,7 +48,7 @@ public interface PredicateSpecification extends Serializable {
* @param the type of the {@link Root} the resulting {@literal PredicateSpecification} operates on.
* @return guaranteed to be not {@literal null}.
*/
- static PredicateSpecification all() {
+ static PredicateSpecification unrestricted() {
return (root, builder) -> null;
}
@@ -104,13 +110,14 @@ static PredicateSpecification not(PredicateSpecification spec) {
return (root, builder) -> {
- Predicate not = spec.toPredicate(root, builder);
- return not != null ? builder.not(not) : null;
+ Predicate predicate = spec.toPredicate(root, builder);
+ return predicate != null ? builder.not(predicate) : null;
};
}
/**
- * Applies an AND operation to all the given {@link PredicateSpecification}s.
+ * Applies an AND operation to all the given {@link PredicateSpecification}s. If {@code specifications} is empty, the
+ * resulting {@link PredicateSpecification} will be unrestricted applying to all objects.
*
* @param specifications the {@link PredicateSpecification}s to compose.
* @return the conjunction of the specifications.
@@ -123,7 +130,8 @@ static PredicateSpecification allOf(PredicateSpecification... specific
}
/**
- * Applies an AND operation to all the given {@link PredicateSpecification}s.
+ * Applies an AND operation to all the given {@link PredicateSpecification}s. If {@code specifications} is empty, the
+ * resulting {@link PredicateSpecification} will be unrestricted applying to all objects.
*
* @param specifications the {@link PredicateSpecification}s to compose.
* @return the conjunction of the specifications.
@@ -133,11 +141,12 @@ static PredicateSpecification allOf(PredicateSpecification... specific
static PredicateSpecification allOf(Iterable> specifications) {
return StreamSupport.stream(specifications.spliterator(), false) //
- .reduce(PredicateSpecification.all(), PredicateSpecification::and);
+ .reduce(PredicateSpecification.unrestricted(), PredicateSpecification::and);
}
/**
- * Applies an OR operation to all the given {@link PredicateSpecification}s.
+ * Applies an OR operation to all the given {@link PredicateSpecification}s. If {@code specifications} is empty, the
+ * resulting {@link PredicateSpecification} will be unrestricted applying to all objects.
*
* @param specifications the {@link PredicateSpecification}s to compose.
* @return the disjunction of the specifications.
@@ -150,7 +159,8 @@ static PredicateSpecification anyOf(PredicateSpecification... specific
}
/**
- * Applies an OR operation to all the given {@link PredicateSpecification}s.
+ * Applies an OR operation to all the given {@link PredicateSpecification}s. If {@code specifications} is empty, the
+ * resulting {@link PredicateSpecification} will be unrestricted applying to all objects.
*
* @param specifications the {@link PredicateSpecification}s to compose.
* @return the disjunction of the specifications.
@@ -160,7 +170,7 @@ static PredicateSpecification anyOf(PredicateSpecification... specific
static PredicateSpecification anyOf(Iterable> specifications) {
return StreamSupport.stream(specifications.spliterator(), false) //
- .reduce(PredicateSpecification.all(), PredicateSpecification::or);
+ .reduce(PredicateSpecification.unrestricted(), PredicateSpecification::or);
}
/**
diff --git a/spring-data-jpa/src/main/java/org/springframework/data/jpa/domain/Specification.java b/spring-data-jpa/src/main/java/org/springframework/data/jpa/domain/Specification.java
index 975d52d6ec..b0b44dc0f6 100644
--- a/spring-data-jpa/src/main/java/org/springframework/data/jpa/domain/Specification.java
+++ b/spring-data-jpa/src/main/java/org/springframework/data/jpa/domain/Specification.java
@@ -32,6 +32,12 @@
/**
* Specification in the sense of Domain Driven Design.
+ *
+ * Specifications can be composed into higher order functions from other specifications using
+ * {@link #and(Specification)}, {@link #or(Specification)} or factory methods such as {@link #allOf(Iterable)}.
+ * Composition considers whether one or more specifications contribute to the overall predicate by returning a
+ * {@link Predicate} or {@literal null}. Specifications returning {@literal null} are considered to not contribute to
+ * the overall predicate and their result is not considered in the final predicate.
*
* @author Oliver Gierke
* @author Thomas Darimont
@@ -51,7 +57,7 @@ public interface Specification extends Serializable {
* @param the type of the {@link Root} the resulting {@literal Specification} operates on.
* @return guaranteed to be not {@literal null}.
*/
- static Specification all() {
+ static Specification unrestricted() {
return (root, query, builder) -> null;
}
@@ -148,13 +154,14 @@ static Specification not(Specification spec) {
return (root, query, builder) -> {
- Predicate not = spec.toPredicate(root, query, builder);
- return not != null ? builder.not(not) : null;
+ Predicate predicate = spec.toPredicate(root, query, builder);
+ return predicate != null ? builder.not(predicate) : null;
};
}
/**
- * Applies an AND operation to all the given {@link Specification}s.
+ * Applies an AND operation to all the given {@link Specification}s. If {@code specifications} is empty, the resulting
+ * {@link Specification} will be unrestricted applying to all objects.
*
* @param specifications the {@link Specification}s to compose.
* @return the conjunction of the specifications.
@@ -168,7 +175,8 @@ static Specification allOf(Specification... specifications) {
}
/**
- * Applies an AND operation to all the given {@link Specification}s.
+ * Applies an AND operation to all the given {@link Specification}s. If {@code specifications} is empty, the resulting
+ * {@link Specification} will be unrestricted applying to all objects.
*
* @param specifications the {@link Specification}s to compose.
* @return the conjunction of the specifications.
@@ -179,11 +187,12 @@ static Specification allOf(Specification... specifications) {
static Specification allOf(Iterable> specifications) {
return StreamSupport.stream(specifications.spliterator(), false) //
- .reduce(Specification.all(), Specification::and);
+ .reduce(Specification.unrestricted(), Specification::and);
}
/**
- * Applies an OR operation to all the given {@link Specification}s.
+ * Applies an OR operation to all the given {@link Specification}s. If {@code specifications} is empty, the resulting
+ * {@link Specification} will be unrestricted applying to all objects.
*
* @param specifications the {@link Specification}s to compose.
* @return the disjunction of the specifications
@@ -197,7 +206,8 @@ static Specification anyOf(Specification... specifications) {
}
/**
- * Applies an OR operation to all the given {@link Specification}s.
+ * Applies an OR operation to all the given {@link Specification}s. If {@code specifications} is empty, the resulting
+ * {@link Specification} will be unrestricted applying to all objects.
*
* @param specifications the {@link Specification}s to compose.
* @return the disjunction of the specifications
@@ -208,7 +218,7 @@ static Specification anyOf(Specification... specifications) {
static Specification anyOf(Iterable> specifications) {
return StreamSupport.stream(specifications.spliterator(), false) //
- .reduce(Specification.all(), Specification::or);
+ .reduce(Specification.unrestricted(), Specification::or);
}
/**
diff --git a/spring-data-jpa/src/main/java/org/springframework/data/jpa/domain/UpdateSpecification.java b/spring-data-jpa/src/main/java/org/springframework/data/jpa/domain/UpdateSpecification.java
index 7667faa9c4..2e9d93b82a 100644
--- a/spring-data-jpa/src/main/java/org/springframework/data/jpa/domain/UpdateSpecification.java
+++ b/spring-data-jpa/src/main/java/org/springframework/data/jpa/domain/UpdateSpecification.java
@@ -31,6 +31,12 @@
/**
* Specification in the sense of Domain Driven Design to handle Criteria Updates.
+ *
+ * Specifications can be composed into higher order functions from other specifications using
+ * {@link #and(UpdateSpecification)}, {@link #or(UpdateSpecification)} or factory methods such as
+ * {@link #allOf(Iterable)}. Composition considers whether one or more specifications contribute to the overall
+ * predicate by returning a {@link Predicate} or {@literal null}. Specifications returning {@literal null} are
+ * considered to not contribute to the overall predicate and their result is not considered in the final predicate.
*
* @author Mark Paluch
* @since 4.0
@@ -39,27 +45,27 @@
public interface UpdateSpecification extends Serializable {
/**
- * Simple static factory method to create a specification deleting all objects.
+ * Simple static factory method to create a specification updating all objects.
*
* @param the type of the {@link Root} the resulting {@literal UpdateSpecification} operates on.
* @return guaranteed to be not {@literal null}.
*/
- static UpdateSpecification all() {
+ static UpdateSpecification unrestricted() {
return (root, query, builder) -> null;
}
/**
- * Simple static factory method to add some syntactic sugar around a {@literal UpdateSpecification}. For example:
+ * Simple static factory method to add some syntactic sugar around a {@literal UpdateOperation}. For example:
*
*
*
- * @param the type of the {@link Root} the resulting {@literal UpdateSpecification} operates on.
+ * @param the type of the {@link Root} the resulting {@literal UpdateOperation} operates on.
* @param spec must not be {@literal null}.
* @return guaranteed to be not {@literal null}.
*/
@@ -172,13 +178,14 @@ static UpdateSpecification not(UpdateSpecification spec) {
return (root, update, builder) -> {
- Predicate not = spec.toPredicate(root, update, builder);
- return not != null ? builder.not(not) : null;
+ Predicate predicate = spec.toPredicate(root, update, builder);
+ return predicate != null ? builder.not(predicate) : null;
};
}
/**
- * Applies an AND operation to all the given {@link UpdateSpecification}s.
+ * Applies an AND operation to all the given {@link UpdateSpecification}s. If {@code specifications} is empty, the
+ * resulting {@link UpdateSpecification} will be unrestricted applying to all objects.
*
* @param specifications the {@link UpdateSpecification}s to compose.
* @return the conjunction of the specifications.
@@ -191,7 +198,8 @@ static UpdateSpecification allOf(UpdateSpecification... specifications
}
/**
- * Applies an AND operation to all the given {@link UpdateSpecification}s.
+ * Applies an AND operation to all the given {@link UpdateSpecification}s. If {@code specifications} is empty, the
+ * resulting {@link UpdateSpecification} will be unrestricted applying to all objects.
*
* @param specifications the {@link UpdateSpecification}s to compose.
* @return the conjunction of the specifications.
@@ -201,11 +209,12 @@ static UpdateSpecification allOf(UpdateSpecification... specifications
static UpdateSpecification allOf(Iterable> specifications) {
return StreamSupport.stream(specifications.spliterator(), false) //
- .reduce(UpdateSpecification.all(), UpdateSpecification::and);
+ .reduce(UpdateSpecification.unrestricted(), UpdateSpecification::and);
}
/**
- * Applies an OR operation to all the given {@link UpdateSpecification}s.
+ * Applies an OR operation to all the given {@link UpdateSpecification}s. If {@code specifications} is empty, the
+ * resulting {@link UpdateSpecification} will be unrestricted applying to all objects.
*
* @param specifications the {@link UpdateSpecification}s to compose.
* @return the disjunction of the specifications.
@@ -218,7 +227,8 @@ static UpdateSpecification anyOf(UpdateSpecification... specifications
}
/**
- * Applies an OR operation to all the given {@link UpdateSpecification}s.
+ * Applies an OR operation to all the given {@link UpdateSpecification}s. If {@code specifications} is empty, the
+ * resulting {@link UpdateSpecification} will be unrestricted applying to all objects.
*
* @param specifications the {@link UpdateSpecification}s to compose.
* @return the disjunction of the specifications.
@@ -228,7 +238,7 @@ static UpdateSpecification anyOf(UpdateSpecification... specifications
static UpdateSpecification anyOf(Iterable> specifications) {
return StreamSupport.stream(specifications.spliterator(), false) //
- .reduce(UpdateSpecification.all(), UpdateSpecification::or);
+ .reduce(UpdateSpecification.unrestricted(), UpdateSpecification::or);
}
/**
diff --git a/spring-data-jpa/src/main/java/org/springframework/data/jpa/repository/JpaSpecificationExecutor.java b/spring-data-jpa/src/main/java/org/springframework/data/jpa/repository/JpaSpecificationExecutor.java
index 1965aaee7b..ec32ec4e77 100644
--- a/spring-data-jpa/src/main/java/org/springframework/data/jpa/repository/JpaSpecificationExecutor.java
+++ b/spring-data-jpa/src/main/java/org/springframework/data/jpa/repository/JpaSpecificationExecutor.java
@@ -49,7 +49,7 @@ public interface JpaSpecificationExecutor {
* @param spec must not be {@literal null}.
* @return never {@literal null}.
* @throws org.springframework.dao.IncorrectResultSizeDataAccessException if more than one entity found.
- * @see Specification#all()
+ * @see Specification#unrestricted()
*/
default Optional findOne(PredicateSpecification spec) {
return findOne(Specification.where(spec));
@@ -61,7 +61,7 @@ default Optional findOne(PredicateSpecification spec) {
* @param spec must not be {@literal null}.
* @return never {@literal null}.
* @throws org.springframework.dao.IncorrectResultSizeDataAccessException if more than one entity found.
- * @see Specification#all()
+ * @see Specification#unrestricted()
*/
Optional findOne(Specification spec);
@@ -70,7 +70,7 @@ default Optional findOne(PredicateSpecification spec) {
*
* @param spec must not be {@literal null}.
* @return never {@literal null}.
- * @see Specification#all()
+ * @see Specification#unrestricted()
*/
default List findAll(PredicateSpecification spec) {
return findAll(Specification.where(spec));
@@ -81,7 +81,7 @@ default List findAll(PredicateSpecification spec) {
*
* @param spec must not be {@literal null}.
* @return never {@literal null}.
- * @see Specification#all()
+ * @see Specification#unrestricted()
*/
List findAll(Specification spec);
@@ -91,7 +91,7 @@ default List findAll(PredicateSpecification spec) {
* @param spec must not be {@literal null}.
* @param pageable must not be {@literal null}.
* @return never {@literal null}.
- * @see Specification#all()
+ * @see Specification#unrestricted()
*/
Page findAll(Specification spec, Pageable pageable);
@@ -101,7 +101,7 @@ default List findAll(PredicateSpecification spec) {
* @param spec must not be {@literal null}.
* @param sort must not be {@literal null}.
* @return never {@literal null}.
- * @see Specification#all()
+ * @see Specification#unrestricted()
*/
List findAll(Specification spec, Sort sort);
@@ -110,7 +110,7 @@ default List findAll(PredicateSpecification spec) {
*
* @param spec the {@link PredicateSpecification} to count instances for, must not be {@literal null}.
* @return the number of instances.
- * @see Specification#all()
+ * @see Specification#unrestricted()
*/
default long count(PredicateSpecification spec) {
return count(Specification.where(spec));
@@ -121,7 +121,7 @@ default long count(PredicateSpecification spec) {
*
* @param spec the {@link Specification} to count instances for, must not be {@literal null}.
* @return the number of instances.
- * @see Specification#all()
+ * @see Specification#unrestricted()
*/
long count(Specification spec);
@@ -131,7 +131,7 @@ default long count(PredicateSpecification spec) {
* @param spec the {@link PredicateSpecification} to use for the existence check, must not be {@literal null}.
* @return {@code true} if the data store contains elements that match the given {@link PredicateSpecification}
* otherwise {@code false}.
- * @see Specification#all()
+ * @see Specification#unrestricted()
*/
default boolean exists(PredicateSpecification spec) {
return exists(Specification.where(spec));
@@ -143,7 +143,7 @@ default boolean exists(PredicateSpecification spec) {
* @param spec the {@link Specification} to use for the existence check, must not be {@literal null}.
* @return {@code true} if the data store contains elements that match the given {@link Specification} otherwise
* {@code false}.
- * @see Specification#all()
+ * @see Specification#unrestricted()
*/
boolean exists(Specification spec);
@@ -168,7 +168,7 @@ default boolean exists(PredicateSpecification spec) {
* @param spec the {@link PredicateSpecification} to use for the delete query, must not be {@literal null}.
* @return the number of entities deleted.
* @since 3.0
- * @see PredicateSpecification#all()
+ * @see PredicateSpecification#unrestricted()
*/
default long delete(PredicateSpecification spec) {
return delete(DeleteSpecification.where(spec));
@@ -183,7 +183,7 @@ default long delete(PredicateSpecification spec) {
* @param spec the {@link UpdateSpecification} to use for the delete query must not be {@literal null}.
* @return the number of entities deleted.
* @since 3.0
- * @see DeleteSpecification#all()
+ * @see DeleteSpecification#unrestricted()
*/
long delete(DeleteSpecification spec);
diff --git a/spring-data-jpa/src/main/java/org/springframework/data/jpa/repository/support/SimpleJpaRepository.java b/spring-data-jpa/src/main/java/org/springframework/data/jpa/repository/support/SimpleJpaRepository.java
index 3c137b4329..ff3d19a20f 100644
--- a/spring-data-jpa/src/main/java/org/springframework/data/jpa/repository/support/SimpleJpaRepository.java
+++ b/spring-data-jpa/src/main/java/org/springframework/data/jpa/repository/support/SimpleJpaRepository.java
@@ -392,7 +392,7 @@ public boolean existsById(ID id) {
@Override
public List findAll() {
- return getQuery(Specification.all(), Sort.unsorted()).getResultList();
+ return getQuery(Specification.unrestricted(), Sort.unsorted()).getResultList();
}
@Override
@@ -425,12 +425,12 @@ public List findAllById(Iterable ids) {
@Override
public List findAll(Sort sort) {
- return getQuery(Specification.all(), sort).getResultList();
+ return getQuery(Specification.unrestricted(), sort).getResultList();
}
@Override
public Page findAll(Pageable pageable) {
- return findAll(Specification.all(), pageable);
+ return findAll(Specification.unrestricted(), pageable);
}
@Override
@@ -1016,7 +1016,7 @@ private static long executeCountQuery(TypedQuery query) {
@SuppressWarnings("rawtypes")
private static final class ByIdsSpecification implements Specification {
- @Serial private static final @Serial long serialVersionUID = 1L;
+ private static final @Serial long serialVersionUID = 1L;
private final JpaEntityInformation entityInformation;
@@ -1046,7 +1046,7 @@ public Predicate toPredicate(Root root, CriteriaQuery> query, CriteriaBuild
*/
private static class ExampleSpecification implements Specification {
- @Serial private static final @Serial long serialVersionUID = 1L;
+ private static final @Serial long serialVersionUID = 1L;
private final Example example;
private final EscapeCharacter escapeCharacter;
diff --git a/spring-data-jpa/src/test/java/org/springframework/data/jpa/domain/DeleteSpecificationUnitTests.java b/spring-data-jpa/src/test/java/org/springframework/data/jpa/domain/DeleteSpecificationUnitTests.java
index 79e531ad7f..02e59fa2db 100644
--- a/spring-data-jpa/src/test/java/org/springframework/data/jpa/domain/DeleteSpecificationUnitTests.java
+++ b/spring-data-jpa/src/test/java/org/springframework/data/jpa/domain/DeleteSpecificationUnitTests.java
@@ -59,7 +59,7 @@ void setUp() {
@Test // GH-3521
void allReturnsEmptyPredicate() {
- DeleteSpecification