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 310ed0c6d..3337ae5fb 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 @@ import org.springframework.util.Assert;
/**
* 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 @@ public interface DeleteSpecification extends Serializable {
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 @@ public interface DeleteSpecification extends Serializable {
}
/**
- * 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 @@ public interface DeleteSpecification extends Serializable {
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 @@ public interface DeleteSpecification extends Serializable {
}
/**
- * 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 @@ public interface DeleteSpecification extends Serializable {
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 f237715bc..dc17edbfc 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 @@ import org.springframework.util.Assert;
/**
* 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 @@ public interface PredicateSpecification extends Serializable {
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 @@ public interface PredicateSpecification extends Serializable {
}
/**
- * 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 @@ public interface PredicateSpecification extends Serializable {
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 @@ public interface PredicateSpecification extends Serializable {
}
/**
- * 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 @@ public interface PredicateSpecification extends Serializable {
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 975d52d6e..b0b44dc0f 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 @@ import org.springframework.util.Assert;
/**
* 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 @@ public interface Specification extends Serializable {
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 @@ public interface Specification extends Serializable {
}
/**
- * 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 @@ public interface Specification extends Serializable {
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 @@ public interface Specification extends Serializable {
}
/**
- * 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 @@ public interface Specification extends Serializable {
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 7667faa9c..2e9d93b82 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 @@ import org.springframework.util.Assert;
/**
* 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 @@ import org.springframework.util.Assert;
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 @@ public interface UpdateSpecification extends Serializable {
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 @@ public interface UpdateSpecification extends Serializable {
}
/**
- * 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 @@ public interface UpdateSpecification extends Serializable {
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 @@ public interface UpdateSpecification extends Serializable {
}
/**
- * 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 @@ public interface UpdateSpecification extends Serializable {
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 f4fac7951..65e352105 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
@@ -60,7 +60,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));
@@ -72,7 +72,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()
*/
Optional findOne(Specification spec);
@@ -81,7 +81,7 @@ public interface JpaSpecificationExecutor {
*
* @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));
@@ -92,7 +92,7 @@ public interface JpaSpecificationExecutor {
*
* @param spec must not be {@literal null}.
* @return never {@literal null}.
- * @see Specification#all()
+ * @see Specification#unrestricted()
*/
List findAll(Specification spec);
@@ -102,7 +102,7 @@ public interface JpaSpecificationExecutor {
* @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);
@@ -128,7 +128,7 @@ public interface JpaSpecificationExecutor {
* @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);
@@ -137,7 +137,7 @@ public interface JpaSpecificationExecutor {
*
* @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));
@@ -148,7 +148,7 @@ public interface JpaSpecificationExecutor {
*
* @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);
@@ -158,7 +158,7 @@ public interface JpaSpecificationExecutor {
* @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));
@@ -170,7 +170,7 @@ public interface JpaSpecificationExecutor {
* @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);
@@ -195,7 +195,7 @@ public interface JpaSpecificationExecutor {
* @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));
@@ -210,7 +210,7 @@ public interface JpaSpecificationExecutor {
* @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 99d25f49d..dbbdea2d1 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
@@ -401,7 +401,7 @@ public class SimpleJpaRepository implements JpaRepositoryImplementation findAll() {
- return getQuery(Specification.all(), Sort.unsorted()).getResultList();
+ return getQuery(Specification.unrestricted(), Sort.unsorted()).getResultList();
}
@Override
@@ -434,12 +434,12 @@ public class SimpleJpaRepository implements JpaRepositoryImplementation 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
@@ -1094,7 +1094,7 @@ public class SimpleJpaRepository implements JpaRepositoryImplementation implements Specification {
- @Serial private static final @Serial long serialVersionUID = 1L;
+ private static final @Serial long serialVersionUID = 1L;
private final JpaEntityInformation entityInformation;
@@ -1124,7 +1124,7 @@ public class SimpleJpaRepository implements JpaRepositoryImplementation 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 79e531ad7..02e59fa2d 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 @@ class DeleteSpecificationUnitTests implements Serializable {
@Test // GH-3521
void allReturnsEmptyPredicate() {
- DeleteSpecification