Skip to content

Commit a1fbb5a

Browse files
nam0oomp911de
authored andcommitted
Reintroduce Specification.where(Specification)
Reintroduce the overload to improve the migration path for users upgrading to Spring Data JPA 4.0 and to restore the intuitive fluent API but this time, the method does not accept null values. Closes #3992 Original pull request: #3998 Signed-off-by: 희은 <[email protected]>
1 parent 8ffc585 commit a1fbb5a

File tree

2 files changed

+47
-0
lines changed

2 files changed

+47
-0
lines changed

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

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@
4848
* @author Jens Schauder
4949
* @author Daniel Shuy
5050
* @author Sergey Rukin
51+
* @author Heeeun Cho
5152
*/
5253
@FunctionalInterface
5354
public interface Specification<T> extends Serializable {
@@ -78,6 +79,21 @@ static <T> Specification<T> where(PredicateSpecification<T> spec) {
7879
return (root, update, criteriaBuilder) -> spec.toPredicate(root, criteriaBuilder);
7980
}
8081

82+
/**
83+
* Creates a {@link Specification} from the given {@link Specification}. This is a factory method for fluent composition.
84+
*
85+
* @param <T> the type of the {@link Root} the resulting {@literal Specification} operates on.
86+
* @param spec must not be {@literal null}.
87+
* @return the given specification.
88+
* @since 4.1
89+
*/
90+
static <T> Specification<T> where(Specification<T> spec) {
91+
92+
Assert.notNull(spec, "Specification must not be null");
93+
94+
return spec;
95+
}
96+
8197
/**
8298
* ANDs the given {@link Specification} to the current one.
8399
*

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

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@
4242
* @author Jens Schauder
4343
* @author Mark Paluch
4444
* @author Daniel Shuy
45+
* @author Heeeun Cho
4546
*/
4647
@SuppressWarnings({ "unchecked", "deprecation" })
4748
@ExtendWith(MockitoExtension.class)
@@ -137,6 +138,36 @@ void notWithNullPredicate() {
137138
verify(builder).disjunction();
138139
}
139140

141+
@Test // GH-3992
142+
void whereWithSpecificationReturnsSameSpecification() {
143+
144+
Specification<Object> originalSpec = (r, q, cb) -> predicate;
145+
Specification<Object> wrappedSpec = Specification.where(originalSpec);
146+
147+
assertThat(wrappedSpec).isSameAs(originalSpec);
148+
}
149+
150+
@Test // GH-3992
151+
void whereWithSpecificationSupportsFluentComposition() {
152+
153+
Specification<Object> firstSpec = (r, q, cb) -> predicate;
154+
Specification<Object> secondSpec = (r, q, cb) -> predicate;
155+
156+
Specification<Object> composedSpec = Specification.where(firstSpec).and(secondSpec);
157+
158+
assertThat(composedSpec).isNotNull();
159+
composedSpec.toPredicate(root, query, builder);
160+
verify(builder).and(predicate, predicate);
161+
}
162+
163+
@Test // GH-3992
164+
void whereWithNullSpecificationThrowsException() {
165+
166+
assertThatThrownBy(() -> Specification.where((Specification<Object>) null))
167+
.isInstanceOf(IllegalArgumentException.class)
168+
.hasMessage("Specification must not be null");
169+
}
170+
140171
static class SerializableSpecification implements Serializable, Specification<Object> {
141172

142173
@Override

0 commit comments

Comments
 (0)