From 3046aa8bab4012eb44d0a0f3bf40897dbd359497 Mon Sep 17 00:00:00 2001 From: SWQXDBA <983110853@qq.com> Date: Wed, 23 Apr 2025 20:03:17 +0800 Subject: [PATCH] Fix handling of null predicate in Specification.not() #3849 When toPredicate() returns null, Specification.not() now returns builder.disjunction() instead of builder.not(null). This change ensures proper handling of null predicates in negated specifications. Signed-off-by: SWQXDBA <983110853@qq.com> --- .../data/jpa/domain/Specification.java | 8 +++++++- .../data/jpa/domain/SpecificationUnitTests.java | 11 +++++++++++ 2 files changed, 18 insertions(+), 1 deletion(-) 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 4586bf76f7..c4ad2416a1 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 @@ -56,7 +56,13 @@ static Specification not(@Nullable Specification spec) { return spec == null // ? (root, query, builder) -> null // - : (root, query, builder) -> builder.not(spec.toPredicate(root, query, builder)); + : (root, query, builder) -> { + Predicate predicate = spec.toPredicate(root, query, builder); + if(predicate != null) { + return builder.not(predicate); + } + return builder.disjunction(); + }; } /** diff --git a/spring-data-jpa/src/test/java/org/springframework/data/jpa/domain/SpecificationUnitTests.java b/spring-data-jpa/src/test/java/org/springframework/data/jpa/domain/SpecificationUnitTests.java index 368ccc7ff5..96269d0ef3 100644 --- a/spring-data-jpa/src/test/java/org/springframework/data/jpa/domain/SpecificationUnitTests.java +++ b/spring-data-jpa/src/test/java/org/springframework/data/jpa/domain/SpecificationUnitTests.java @@ -214,6 +214,17 @@ void orCombinesSpecificationsInOrder() { verify(builder).or(firstPredicate, secondPredicate); } + @Test // #3849 + void notWithNullPredicate() { + Specification spec = (r, q, cb) -> null; + + Specification notSpec = Specification.not(spec); + + notSpec.toPredicate(root, query, builder); + + verify(builder).disjunction(); + } + static class SerializableSpecification implements Serializable, Specification { @Override