diff --git a/jpa/example/src/main/java/example/springdata/jpa/projections/CustomerRepository.java b/jpa/example/src/main/java/example/springdata/jpa/projections/CustomerRepository.java index 752c3e88c..2ab0cd7c8 100644 --- a/jpa/example/src/main/java/example/springdata/jpa/projections/CustomerRepository.java +++ b/jpa/example/src/main/java/example/springdata/jpa/projections/CustomerRepository.java @@ -21,13 +21,15 @@ import org.springframework.beans.factory.annotation.Value; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; +import org.springframework.data.jpa.domain.Specification; +import org.springframework.data.jpa.repository.JpaSpecificationExecutor; import org.springframework.data.jpa.repository.Query; import org.springframework.data.repository.CrudRepository; /** * @author Oliver Gierke */ -public interface CustomerRepository extends CrudRepository { +public interface CustomerRepository extends CrudRepository, JpaSpecificationExecutor { /** * Uses a projection interface to indicate the fields to be returned. As the projection doesn't use any dynamic @@ -113,4 +115,23 @@ public interface CustomerRepository extends CrudRepository { * @return */ Optional findOptionalProjectionByLastname(String lastname); + + /** + * Dynamic projections used with specification. + * + * @pafam spec + * @param projection + * @return + */ + Collection findProjectedBy(Specification spec, Class projection); + + /** + * Dynamic projections used with pagination and specification. + * + * @pafam spec + * @param pageable + * @param projection + * @return + */ + Page findPagedProjectedBy(Specification spec, Pageable pageable, Class projection); } diff --git a/jpa/example/src/test/java/example/springdata/jpa/projections/CustomerRepositoryIntegrationTest.java b/jpa/example/src/test/java/example/springdata/jpa/projections/CustomerRepositoryIntegrationTest.java index 4573ae37f..821d87e56 100644 --- a/jpa/example/src/test/java/example/springdata/jpa/projections/CustomerRepositoryIntegrationTest.java +++ b/jpa/example/src/test/java/example/springdata/jpa/projections/CustomerRepositoryIntegrationTest.java @@ -32,10 +32,16 @@ import org.springframework.data.domain.PageRequest; import org.springframework.data.domain.Sort; import org.springframework.data.domain.Sort.Direction; +import org.springframework.data.jpa.domain.Specification; import org.springframework.data.projection.TargetAware; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import org.springframework.transaction.annotation.Transactional; +import javax.persistence.criteria.CriteriaBuilder; +import javax.persistence.criteria.CriteriaQuery; +import javax.persistence.criteria.Predicate; +import javax.persistence.criteria.Root; + /** * Integration tests for {@link CustomerRepository} to show projection capabilities. * @@ -139,4 +145,34 @@ public void supportsProjectionInCombinationWithPagination() { public void appliesProjectionToOptional() { assertThat(customers.findOptionalProjectionByLastname("Beauford").isPresent(), is(true)); } + + @Test + public void supportsDynamicProjectionInCombinationWitSpecification() { + + Collection result = customers + .findProjectedBy(firstNameIs("Dave"), CustomerProjection.class); + + assertThat(result, hasSize(1)); + } + + @Test + public void supportsDynamicProjectionInCombinationWithPaginationAndSpecification() { + + Page page = customers + .findPagedProjectedBy(firstNameIs("Dave"), new PageRequest(0, 1, new Sort(Direction.ASC, "lastname")), + CustomerProjection.class); + + assertThat(page.getTotalElements(), is(1)); + } + + protected static Specification firstNameIs(String firstName) { + return new Specification() { + + @Override + public Predicate toPredicate(final Root root, final CriteriaQuery query, + final CriteriaBuilder cb) { + return cb.equal(root.get("firstName"), firstName); + } + }; + } }