diff --git a/spring-data-jpa/src/main/java/org/springframework/data/jpa/repository/query/PartTreeJpaQuery.java b/spring-data-jpa/src/main/java/org/springframework/data/jpa/repository/query/PartTreeJpaQuery.java index 479dc4b52..3b799258d 100644 --- a/spring-data-jpa/src/main/java/org/springframework/data/jpa/repository/query/PartTreeJpaQuery.java +++ b/spring-data-jpa/src/main/java/org/springframework/data/jpa/repository/query/PartTreeJpaQuery.java @@ -259,8 +259,8 @@ public class PartTreeJpaQuery extends AbstractJpaQuery { @SuppressWarnings("ConstantConditions") private Query restrictMaxResultsIfNecessary(Query query, @Nullable ScrollPosition scrollPosition) { - if (scrollPosition instanceof OffsetScrollPosition offset) { - query.setFirstResult(Math.toIntExact(offset.getOffset())); + if (scrollPosition instanceof OffsetScrollPosition offset && !offset.isInitial()) { + query.setFirstResult(Math.toIntExact(offset.getOffset()) + 1); } if (tree.isLimiting()) { diff --git a/spring-data-jpa/src/main/java/org/springframework/data/jpa/repository/query/ScrollDelegate.java b/spring-data-jpa/src/main/java/org/springframework/data/jpa/repository/query/ScrollDelegate.java index 90c055578..d529b73f7 100644 --- a/spring-data-jpa/src/main/java/org/springframework/data/jpa/repository/query/ScrollDelegate.java +++ b/spring-data-jpa/src/main/java/org/springframework/data/jpa/repository/query/ScrollDelegate.java @@ -71,7 +71,7 @@ public class ScrollDelegate { } if (scrollPosition instanceof OffsetScrollPosition offset) { - return createWindow(result, limit, OffsetScrollPosition.positionFunction(offset.getOffset())); + return createWindow(result, limit, OffsetScrollPosition.positionFunction(offset.isInitial() ? 0 : offset.getOffset())); } throw new UnsupportedOperationException("ScrollPosition " + scrollPosition + " not supported"); diff --git a/spring-data-jpa/src/main/java/org/springframework/data/jpa/repository/support/QuerydslJpaPredicateExecutor.java b/spring-data-jpa/src/main/java/org/springframework/data/jpa/repository/support/QuerydslJpaPredicateExecutor.java index 946dfb23f..606d56631 100644 --- a/spring-data-jpa/src/main/java/org/springframework/data/jpa/repository/support/QuerydslJpaPredicateExecutor.java +++ b/spring-data-jpa/src/main/java/org/springframework/data/jpa/repository/support/QuerydslJpaPredicateExecutor.java @@ -196,7 +196,9 @@ public class QuerydslJpaPredicateExecutor implements QuerydslPredicateExecuto select = (AbstractJPAQuery) querydsl.applySorting(sort, select); if (scrollPosition instanceof OffsetScrollPosition offset) { - select.offset(offset.getOffset()); + if(!offset.isInitial()) { + select.offset(offset.getOffset() + 1); + } } return select.createQuery(); 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 31abc1918..879e68386 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 @@ -512,7 +512,9 @@ public class SimpleJpaRepository implements JpaRepositoryImplementation query = getQuery(specToUse, domainClass, sort); if (scrollPosition instanceof OffsetScrollPosition offset) { - query.setFirstResult(Math.toIntExact(offset.getOffset())); + if(!offset.isInitial()) { + query.setFirstResult(Math.toIntExact(offset.getOffset()) + 1); + } } return query; diff --git a/spring-data-jpa/src/test/java/org/springframework/data/jpa/repository/UserRepositoryFinderTests.java b/spring-data-jpa/src/test/java/org/springframework/data/jpa/repository/UserRepositoryFinderTests.java index bea13c14a..6a8c06789 100644 --- a/spring-data-jpa/src/test/java/org/springframework/data/jpa/repository/UserRepositoryFinderTests.java +++ b/spring-data-jpa/src/test/java/org/springframework/data/jpa/repository/UserRepositoryFinderTests.java @@ -226,16 +226,16 @@ class UserRepositoryFinderTests { assertThat(slice.hasNext()).isFalse(); } - @Test // DATAJPA-94 + @Test // GH-3077, GH-3409 void executesQueryWithLimitAndScrollPosition() { Window first = userRepository.findByLastnameOrderByFirstname(Limit.of(1), // - ScrollPosition.offset(), // + ScrollPosition.offset(), // initial position no offset "Matthews" // ); Window next = userRepository.findByLastnameOrderByFirstname(Limit.of(1), // - ScrollPosition.offset(1), // + ScrollPosition.offset(0), // first position, offset = 1 "Matthews" // ); @@ -243,6 +243,17 @@ class UserRepositoryFinderTests { assertThat(next).containsExactly(oliver); } + @Test // GH-3409 + void executesWindowQueryWithPageable() { + + Window first = userRepository.findByLastnameOrderByFirstname("Matthews", PageRequest.of(0,1)); + + Window next = userRepository.findByLastnameOrderByFirstname("Matthews", PageRequest.of(1,1)); + + assertThat(first).containsExactly(dave); + assertThat(next).containsExactly(oliver); + } + @Test // GH-3077 void shouldProjectWithKeysetScrolling() { diff --git a/spring-data-jpa/src/test/java/org/springframework/data/jpa/repository/UserRepositoryTests.java b/spring-data-jpa/src/test/java/org/springframework/data/jpa/repository/UserRepositoryTests.java index 4b802f977..6f7072470 100644 --- a/spring-data-jpa/src/test/java/org/springframework/data/jpa/repository/UserRepositoryTests.java +++ b/spring-data-jpa/src/test/java/org/springframework/data/jpa/repository/UserRepositoryTests.java @@ -1430,7 +1430,7 @@ class UserRepositoryTests { assertThat(previousWindow.hasNext()).isFalse(); } - @Test // GH-3015 + @Test // GH-3015, GH-3407 void shouldApplyOffsetScrollPosition() { User jane1 = new User("Jane", "Doe", "jane@doe1.com"); @@ -1441,7 +1441,7 @@ class UserRepositoryTests { repository.saveAllAndFlush(Arrays.asList(john1, john2, jane1, jane2)); Window atOffset3 = repository.findByFirstnameStartingWithOrderByFirstnameAscEmailAddressAsc("J", - ScrollPosition.offset(3)); + ScrollPosition.offset(2)); assertThat(atOffset3).containsExactly(john2); } diff --git a/spring-data-jpa/src/test/java/org/springframework/data/jpa/repository/sample/UserRepository.java b/spring-data-jpa/src/test/java/org/springframework/data/jpa/repository/sample/UserRepository.java index 2e782982a..0d898449a 100644 --- a/spring-data-jpa/src/test/java/org/springframework/data/jpa/repository/sample/UserRepository.java +++ b/spring-data-jpa/src/test/java/org/springframework/data/jpa/repository/sample/UserRepository.java @@ -197,6 +197,8 @@ public interface UserRepository extends JpaRepository, JpaSpecifi Window findByLastnameOrderByFirstname(Limit limit, ScrollPosition scrollPosition, String lastname); + Window findByLastnameOrderByFirstname(String lastname, Pageable page); + Window findTop1ByLastnameOrderByFirstname(ScrollPosition scrollPosition, String lastname); List findByLastnameIgnoringCaseLike(String lastname);