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 3125e8430..ad9f2e9a9 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 @@ -15,6 +15,7 @@ */ package org.springframework.data.jpa.repository.query; +import java.util.Collections; import java.util.List; import javax.persistence.EntityManager; @@ -24,6 +25,7 @@ import javax.persistence.TypedQuery; import org.springframework.data.domain.Page; import org.springframework.data.domain.PageImpl; +import org.springframework.data.domain.Pageable; import org.springframework.data.repository.query.ParameterAccessor; import org.springframework.data.repository.query.Parameters; import org.springframework.data.repository.query.ParametersParameterAccessor; @@ -100,8 +102,11 @@ public abstract class JpaQueryExecution { Query query = repositoryQuery.createQuery(values); ParameterAccessor accessor = new ParametersParameterAccessor(parameters, values); + Pageable pageable = accessor.getPageable(); - return new PageImpl(query.getResultList(), accessor.getPageable(), total); + List content = total > pageable.getOffset() ? query.getResultList() : Collections.emptyList(); + + return new PageImpl(content, pageable, total); } } diff --git a/src/main/java/org/springframework/data/jpa/repository/support/SimpleJpaRepository.java b/src/main/java/org/springframework/data/jpa/repository/support/SimpleJpaRepository.java index 9bb84de35..65d019e19 100644 --- a/src/main/java/org/springframework/data/jpa/repository/support/SimpleJpaRepository.java +++ b/src/main/java/org/springframework/data/jpa/repository/support/SimpleJpaRepository.java @@ -19,6 +19,7 @@ import static org.springframework.data.jpa.repository.query.QueryUtils.*; import java.io.Serializable; import java.util.ArrayList; +import java.util.Collections; import java.util.List; import javax.persistence.EntityManager; @@ -352,8 +353,9 @@ public class SimpleJpaRepository implements JpaRepos query.setMaxResults(pageable.getPageSize()); Long total = getCountQuery(spec).getSingleResult(); + List content = total > pageable.getOffset() ? query.getResultList() : Collections. emptyList(); - return new PageImpl(query.getResultList(), pageable, total); + return new PageImpl(content, pageable, total); } /** diff --git a/src/test/java/org/springframework/data/jpa/repository/query/JpaQueryExecutionUnitTests.java b/src/test/java/org/springframework/data/jpa/repository/query/JpaQueryExecutionUnitTests.java index df37a3d57..e8f24ef97 100644 --- a/src/test/java/org/springframework/data/jpa/repository/query/JpaQueryExecutionUnitTests.java +++ b/src/test/java/org/springframework/data/jpa/repository/query/JpaQueryExecutionUnitTests.java @@ -19,15 +19,22 @@ import static org.hamcrest.CoreMatchers.*; import static org.junit.Assert.*; import static org.mockito.Mockito.*; +import java.util.Arrays; + import javax.persistence.EntityManager; import javax.persistence.Query; +import javax.persistence.TypedQuery; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; import org.mockito.Mockito; import org.mockito.runners.MockitoJUnitRunner; +import org.springframework.data.domain.PageRequest; +import org.springframework.data.domain.Pageable; import org.springframework.data.jpa.repository.query.JpaQueryExecution.ModifyingExecution; +import org.springframework.data.jpa.repository.query.JpaQueryExecution.PagedExecution; +import org.springframework.data.repository.query.Parameters; /** * Unit test for {@link JpaQueryExecution}. @@ -46,6 +53,9 @@ public class JpaQueryExecutionUnitTests { @Mock JpaQueryMethod method; + @Mock + TypedQuery countQuery; + @Test(expected = IllegalArgumentException.class) public void rejectsNullQuery() { @@ -104,6 +114,27 @@ public class JpaQueryExecutionUnitTests { new ModifyingExecution(method, em); } + /** + * @see DATAJPA-124 + */ + @Test + public void pagedExecutionDoesNotRetrieveObjectsForPageableOutOfRange() throws Exception { + + Parameters parameters = new Parameters(getClass().getMethod("sampleMethod", Pageable.class)); + when(jpaQuery.createCountQuery(Mockito.any(Object[].class))).thenReturn(countQuery); + when(jpaQuery.createQuery(Mockito.any(Object[].class))).thenReturn(query); + when(countQuery.getResultList()).thenReturn(Arrays.asList(20L)); + + PagedExecution execution = new PagedExecution(parameters); + execution.doExecute(jpaQuery, new Object[] { new PageRequest(2, 10) }); + + verify(query, times(0)).getResultList(); + } + + public static void sampleMethod(Pageable pageable) { + + } + static class StubQueryExecution extends JpaQueryExecution { @Override diff --git a/src/test/java/org/springframework/data/jpa/repository/support/SimpleJpaRepositoryUnitTests.java b/src/test/java/org/springframework/data/jpa/repository/support/SimpleJpaRepositoryUnitTests.java new file mode 100644 index 000000000..d14ea82ea --- /dev/null +++ b/src/test/java/org/springframework/data/jpa/repository/support/SimpleJpaRepositoryUnitTests.java @@ -0,0 +1,81 @@ +/* + * Copyright 2011 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. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.data.jpa.repository.support; + +import static org.mockito.Mockito.*; + +import javax.persistence.EntityManager; +import javax.persistence.TypedQuery; +import javax.persistence.criteria.CriteriaBuilder; +import javax.persistence.criteria.CriteriaQuery; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.runners.MockitoJUnitRunner; +import org.springframework.data.domain.PageRequest; +import org.springframework.data.jpa.domain.sample.User; + +/** + * Unit tests for {@link SimpleJpaRepository}. + * + * @author Oliver Gierke + */ +@RunWith(MockitoJUnitRunner.class) +public class SimpleJpaRepositoryUnitTests { + + SimpleJpaRepository repo; + + @Mock + EntityManager em; + @Mock + CriteriaBuilder builder; + @Mock + CriteriaQuery criteriaQuery; + @Mock + CriteriaQuery countCriteriaQuery; + @Mock + TypedQuery query; + @Mock + TypedQuery countQuery; + @Mock + JpaEntityInformation information; + + @Before + public void setUp() { + + when(information.getJavaType()).thenReturn(User.class); + when(em.getCriteriaBuilder()).thenReturn(builder); + + when(builder.createQuery(User.class)).thenReturn(criteriaQuery); + when(builder.createQuery(Long.class)).thenReturn(countCriteriaQuery); + + when(em.createQuery(criteriaQuery)).thenReturn(query); + when(em.createQuery(countCriteriaQuery)).thenReturn(countQuery); + + repo = new SimpleJpaRepository(information, em); + } + + @Test + public void doesNotActuallyRetrieveObjectsForPageableOutOfRange() { + + when(countQuery.getSingleResult()).thenReturn(20L); + repo.findAll(new PageRequest(2, 10)); + + verify(query, times(0)).getResultList(); + } +}