diff --git a/src/main/java/org/springframework/data/jpa/repository/query/AbstractJpaQuery.java b/src/main/java/org/springframework/data/jpa/repository/query/AbstractJpaQuery.java index 15f0f2e52..5426f47bc 100644 --- a/src/main/java/org/springframework/data/jpa/repository/query/AbstractJpaQuery.java +++ b/src/main/java/org/springframework/data/jpa/repository/query/AbstractJpaQuery.java @@ -25,6 +25,7 @@ import org.springframework.data.jpa.repository.query.JpaQueryExecution.Collectio import org.springframework.data.jpa.repository.query.JpaQueryExecution.ModifyingExecution; import org.springframework.data.jpa.repository.query.JpaQueryExecution.PagedExecution; import org.springframework.data.jpa.repository.query.JpaQueryExecution.SingleEntityExecution; +import org.springframework.data.jpa.repository.query.JpaQueryExecution.SlicedExecution; import org.springframework.data.repository.query.RepositoryQuery; import org.springframework.util.Assert; @@ -100,6 +101,8 @@ public abstract class AbstractJpaQuery implements RepositoryQuery { if (method.isCollectionQuery()) { return new CollectionExecution(); + } else if (method.isSliceQuery()) { + return new SlicedExecution(method.getParameters()); } else if (method.isPageQuery()) { return new PagedExecution(method.getParameters()); } else if (method.isModifyingQuery()) { diff --git a/src/main/java/org/springframework/data/jpa/repository/query/JpaQueryExecution.java b/src/main/java/org/springframework/data/jpa/repository/query/JpaQueryExecution.java index 643f8bf51..a18bcc076 100644 --- a/src/main/java/org/springframework/data/jpa/repository/query/JpaQueryExecution.java +++ b/src/main/java/org/springframework/data/jpa/repository/query/JpaQueryExecution.java @@ -1,5 +1,5 @@ /* - * Copyright 2008-2013 the original author or authors. + * Copyright 2008-2014 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -27,6 +27,8 @@ import org.springframework.core.convert.ConversionService; import org.springframework.core.convert.support.DefaultConversionService; import org.springframework.data.domain.PageImpl; import org.springframework.data.domain.Pageable; +import org.springframework.data.domain.Slice; +import org.springframework.data.domain.SliceImpl; import org.springframework.data.repository.query.ParameterAccessor; import org.springframework.data.repository.query.Parameters; import org.springframework.data.repository.query.ParametersParameterAccessor; @@ -87,7 +89,7 @@ public abstract class JpaQueryExecution { protected abstract Object doExecute(AbstractJpaQuery query, Object[] values); /** - * Executes the {@link AbstractStringBasedJpaQuery} to return a simple collection of entities. + * Executes the query to return a simple collection of entities. */ static class CollectionExecution extends JpaQueryExecution { @@ -97,6 +99,47 @@ public abstract class JpaQueryExecution { } } + /** + * Executes the query to return a {@link Slice} of entities. + * + * @author Oliver Gierke + * @since 1.6 + */ + static class SlicedExecution extends JpaQueryExecution { + + private final Parameters parameters; + + /** + * Creates a new {@link SlicedExecution} using the given {@link Parameters}. + * + * @param parameters must not be {@literal null}. + */ + public SlicedExecution(Parameters parameters) { + this.parameters = parameters; + } + + /* + * (non-Javadoc) + * @see org.springframework.data.jpa.repository.query.JpaQueryExecution#doExecute(org.springframework.data.jpa.repository.query.AbstractJpaQuery, java.lang.Object[]) + */ + @Override + @SuppressWarnings("unchecked") + protected Object doExecute(AbstractJpaQuery query, Object[] values) { + + ParametersParameterAccessor accessor = new ParametersParameterAccessor(parameters, values); + Pageable pageable = accessor.getPageable(); + + Query createQuery = query.createQuery(values); + int pageSize = pageable.getPageSize(); + createQuery.setMaxResults(pageSize + 1); + + List resultList = createQuery.getResultList(); + boolean hasNext = resultList.size() > pageSize; + + return new SliceImpl(hasNext ? resultList.subList(0, pageSize) : resultList, pageable, hasNext); + } + } + /** * Executes the {@link AbstractStringBasedJpaQuery} to return a {@link org.springframework.data.domain.Page} of * entities. diff --git a/src/test/java/org/springframework/data/jpa/repository/UserRepositoryFinderTests.java b/src/test/java/org/springframework/data/jpa/repository/UserRepositoryFinderTests.java index 448aba7df..e5f73e188 100644 --- a/src/test/java/org/springframework/data/jpa/repository/UserRepositoryFinderTests.java +++ b/src/test/java/org/springframework/data/jpa/repository/UserRepositoryFinderTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2008-2011 the original author or authors. + * Copyright 2008-2014 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -17,6 +17,7 @@ package org.springframework.data.jpa.repository; import static org.hamcrest.CoreMatchers.*; import static org.junit.Assert.*; +import static org.springframework.data.domain.Sort.Direction.*; import java.util.Arrays; import java.util.List; @@ -27,8 +28,8 @@ import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.domain.Page; import org.springframework.data.domain.PageRequest; +import org.springframework.data.domain.Slice; import org.springframework.data.domain.Sort; -import org.springframework.data.domain.Sort.Direction; import org.springframework.data.jpa.domain.sample.User; import org.springframework.data.jpa.repository.sample.UserRepository; import org.springframework.data.repository.query.QueryLookupStrategy; @@ -47,8 +48,7 @@ import org.springframework.transaction.annotation.Transactional; @Transactional public class UserRepositoryFinderTests { - @Autowired - UserRepository userRepository; + @Autowired UserRepository userRepository; User dave, carter, oliver; @@ -136,6 +136,9 @@ public class UserRepositoryFinderTests { assertThat(result.get(0), is(oliver)); } + /** + * @see DATAJPA-92 + */ @Test public void findsByLastnameIgnoringCase() throws Exception { List result = userRepository.findByLastnameIgnoringCase("BeAUfoRd"); @@ -143,6 +146,9 @@ public class UserRepositoryFinderTests { assertThat(result.get(0), is(carter)); } + /** + * @see DATAJPA-92 + */ @Test public void findsByLastnameIgnoringCaseLike() throws Exception { List result = userRepository.findByLastnameIgnoringCaseLike("BeAUfo%"); @@ -150,6 +156,9 @@ public class UserRepositoryFinderTests { assertThat(result.get(0), is(carter)); } + /** + * @see DATAJPA-92 + */ @Test public void findByLastnameAndFirstnameAllIgnoringCase() throws Exception { List result = userRepository.findByLastnameAndFirstnameAllIgnoringCase("MaTTheWs", "DaVe"); @@ -157,12 +166,15 @@ public class UserRepositoryFinderTests { assertThat(result.get(0), is(dave)); } + /** + * @see DATAJPA-94 + */ @Test public void respectsPageableOrderOnQueryGenerateFromMethodName() throws Exception { - Page ascending = userRepository.findByLastnameIgnoringCase(new PageRequest(0, 10, new Sort(Direction.ASC, - "firstname")), "Matthews"); - Page descending = userRepository.findByLastnameIgnoringCase(new PageRequest(0, 10, new Sort(Direction.DESC, - "firstname")), "Matthews"); + Page ascending = userRepository.findByLastnameIgnoringCase( + new PageRequest(0, 10, new Sort(ASC, "firstname")), "Matthews"); + Page descending = userRepository.findByLastnameIgnoringCase(new PageRequest(0, 10, + new Sort(DESC, "firstname")), "Matthews"); assertThat(ascending.getTotalElements(), is(2L)); assertThat(descending.getTotalElements(), is(2L)); assertThat(ascending.getContent().get(0).getFirstname(), is(not(equalTo(descending.getContent().get(0) @@ -171,4 +183,15 @@ public class UserRepositoryFinderTests { assertThat(ascending.getContent().get(1).getFirstname(), is(equalTo(descending.getContent().get(0).getFirstname()))); } + /** + * @see DATAJPA-486 + */ + @Test + public void executesQueryToSlice() { + + Slice slice = userRepository.findSliceByLastname("Matthews", new PageRequest(0, 1, ASC, "firstname")); + + assertThat(slice.getContent(), hasItem(dave)); + assertThat(slice.hasNext(), is(true)); + } } diff --git a/src/test/java/org/springframework/data/jpa/repository/sample/UserRepository.java b/src/test/java/org/springframework/data/jpa/repository/sample/UserRepository.java index 5510f80f8..da2225cc8 100644 --- a/src/test/java/org/springframework/data/jpa/repository/sample/UserRepository.java +++ b/src/test/java/org/springframework/data/jpa/repository/sample/UserRepository.java @@ -23,6 +23,7 @@ import javax.persistence.QueryHint; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; +import org.springframework.data.domain.Slice; import org.springframework.data.domain.Sort; import org.springframework.data.jpa.domain.sample.SpecialUser; import org.springframework.data.jpa.domain.sample.User; @@ -305,4 +306,9 @@ public interface UserRepository extends JpaRepository, JpaSpecifi * @see DATAJPA-454 */ List findByBinaryData(byte[] data); + + /** + * @see DATAJPA-486 + */ + Slice findSliceByLastname(String lastname, Pageable pageable); }