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 e7529f6e2..7f59d83bb 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 @@ -24,7 +24,6 @@ import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Sort; import org.springframework.data.jpa.domain.Specification; import org.springframework.data.repository.query.FluentQuery; -import org.springframework.lang.Nullable; /** * Interface to allow execution of {@link Specification}s based on the JPA criteria API. @@ -32,65 +31,66 @@ import org.springframework.lang.Nullable; * @author Oliver Gierke * @author Christoph Strobl * @author Diego Krupitza + * @author Mark Paluch */ public interface JpaSpecificationExecutor { /** * Returns a single entity matching the given {@link Specification} or {@link Optional#empty()} if none found. * - * @param spec can be {@literal null}. + * @param spec must not be {@literal null}. * @return never {@literal null}. * @throws org.springframework.dao.IncorrectResultSizeDataAccessException if more than one entity found. */ - Optional findOne(@Nullable Specification spec); + Optional findOne(Specification spec); /** * Returns all entities matching the given {@link Specification}. * - * @param spec can be {@literal null}. + * @param spec must not be {@literal null}. * @return never {@literal null}. */ - List findAll(@Nullable Specification spec); + List findAll(Specification spec); /** * Returns a {@link Page} of entities matching the given {@link Specification}. * - * @param spec can be {@literal null}. + * @param spec must not be {@literal null}. * @param pageable must not be {@literal null}. * @return never {@literal null}. */ - Page findAll(@Nullable Specification spec, Pageable pageable); + Page findAll(Specification spec, Pageable pageable); /** * Returns all entities matching the given {@link Specification} and {@link Sort}. * - * @param spec can be {@literal null}. + * @param spec must not be {@literal null}. * @param sort must not be {@literal null}. * @return never {@literal null}. */ - List findAll(@Nullable Specification spec, Sort sort); + List findAll(Specification spec, Sort sort); /** * Returns the number of instances that the given {@link Specification} will return. * - * @param spec the {@link Specification} to count instances for. Can be {@literal null}. + * @param spec the {@link Specification} to count instances for, must not be {@literal null}. * @return the number of instances. */ - long count(@Nullable Specification spec); + long count(Specification spec); /** * Checks whether the data store contains elements that match the given {@link Specification}. - * - * @param spec the {@link Specification} to use for the existence check. Must not be {@literal null}. - * @return true if the data store contains elements that match the given {@link Specification} otherwise - * false. + * + * @param spec the {@link Specification} to use for the existence check, ust not be {@literal null}. + * @return {@code true} if the data store contains elements that match the given {@link Specification} otherwise + * {@code false}. */ boolean exists(Specification spec); /** * Deletes by the {@link Specification} and returns the number of rows deleted. * - * @param spec the {@link Specification} to use for the existence check. Must not be {@literal null}. + * @param spec the {@link Specification} to use for the existence check, must not be {@literal null}. * @return the number of entities deleted */ long delete(Specification spec); @@ -99,8 +99,8 @@ public interface JpaSpecificationExecutor { * Returns entities matching the given {@link Specification} applying the {@code queryFunction} that defines the query * and its result type. * - * @param spec – must not be null. - * @param queryFunction – the query function defining projection, sorting, and the result type + * @param spec must not be null. + * @param queryFunction the query function defining projection, sorting, and the result type * @return all entities matching the given Example. * @since 3.0 */ 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 38ea619fa..d83d5f50f 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 @@ -447,7 +447,7 @@ public class SimpleJpaRepository implements JpaRepositoryImplementation findOne(@Nullable Specification spec) { + public Optional findOne(Specification spec) { try { return Optional.of(getQuery(spec, Sort.unsorted()).setMaxResults(2).getSingleResult()); @@ -457,12 +457,12 @@ public class SimpleJpaRepository implements JpaRepositoryImplementation findAll(@Nullable Specification spec) { + public List findAll(Specification spec) { return getQuery(spec, Sort.unsorted()).getResultList(); } @Override - public Page findAll(@Nullable Specification spec, Pageable pageable) { + public Page findAll(Specification spec, Pageable pageable) { TypedQuery query = getQuery(spec, pageable); return isUnpaged(pageable) ? new PageImpl<>(query.getResultList()) @@ -470,10 +470,51 @@ public class SimpleJpaRepository implements JpaRepositoryImplementation findAll(@Nullable Specification spec, Sort sort) { + public List findAll(Specification spec, Sort sort) { return getQuery(spec, sort).getResultList(); } + @Override + public boolean exists(Specification spec) { + + CriteriaQuery cq = this.em.getCriteriaBuilder().createQuery(Integer.class); + cq.select(this.em.getCriteriaBuilder().literal(1)); + applySpecificationToCriteria(spec, getDomainClass(), cq); + TypedQuery query = applyRepositoryMethodMetadata(this.em.createQuery(cq)); + return query.setMaxResults(1).getResultList().size() == 1; + } + + @Override + public long delete(Specification spec) { + + CriteriaBuilder builder = this.em.getCriteriaBuilder(); + CriteriaDelete delete = builder.createCriteriaDelete(getDomainClass()); + + if (spec != null) { + Predicate predicate = spec.toPredicate(delete.from(getDomainClass()), null, builder); + + if (predicate != null) { + delete.where(predicate); + } + } + + return this.em.createQuery(delete).executeUpdate(); + } + + @Override + public R findBy(Specification spec, Function, R> queryFunction) { + + Assert.notNull(spec, "Specification must not be null"); + Assert.notNull(queryFunction, "Query function must not be null"); + + Function> finder = sort -> getQuery(spec, getDomainClass(), sort); + + FetchableFluentQuery fluentQuery = new FetchableFluentQueryBySpecification(spec, getDomainClass(), + Sort.unsorted(), null, finder, this::count, this::exists, this.em); + + return queryFunction.apply((FetchableFluentQuery) fluentQuery); + } + @Override public Optional findOne(Example example) { @@ -503,32 +544,6 @@ public class SimpleJpaRepository implements JpaRepositoryImplementation spec) { - - CriteriaQuery cq = this.em.getCriteriaBuilder().createQuery(Integer.class); - cq.select(this.em.getCriteriaBuilder().literal(1)); - applySpecificationToCriteria(spec, getDomainClass(), cq); - TypedQuery query = applyRepositoryMethodMetadata(this.em.createQuery(cq)); - return query.setMaxResults(1).getResultList().size() == 1; - } - - @Override - public long delete(Specification spec) { - - CriteriaBuilder builder = this.em.getCriteriaBuilder(); - CriteriaDelete delete = builder.createCriteriaDelete(getDomainClass()); - - if (spec != null) { - Predicate predicate = spec.toPredicate(delete.from(getDomainClass()), null, builder); - - if (predicate != null) { - delete.where(predicate); - } - } - - return this.em.createQuery(delete).executeUpdate(); - } @Override public List findAll(Example example) { @@ -571,19 +586,6 @@ public class SimpleJpaRepository implements JpaRepositoryImplementation R findBy(Specification spec, Function, R> queryFunction) { - - Assert.notNull(spec, "Specification must not be null"); - Assert.notNull(queryFunction, "Query function must not be null"); - - Function> finder = sort -> getQuery(spec, getDomainClass(), sort); - - FetchableFluentQuery fluentQuery = new FetchableFluentQueryBySpecification(spec, getDomainClass(), - Sort.unsorted(), null, finder, this::count, this::exists, this.em); - - return queryFunction.apply((FetchableFluentQuery) fluentQuery); - } @Override public long count() {