Skip to content

Commit 1324b29

Browse files
committed
Supports scrolling base on keyset without id
id shouldn't be added to sort if sort property already provided. See GH-2996
1 parent e8d08dd commit 1324b29

File tree

2 files changed

+34
-19
lines changed

2 files changed

+34
-19
lines changed

Diff for: spring-data-jpa/src/main/java/org/springframework/data/jpa/repository/query/KeysetScrollSpecification.java

+8-14
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,6 @@
2222
import jakarta.persistence.criteria.Predicate;
2323
import jakarta.persistence.criteria.Root;
2424

25-
import java.util.ArrayList;
26-
import java.util.Collection;
2725
import java.util.List;
2826

2927
import org.springframework.data.domain.KeysetScrollPosition;
@@ -40,6 +38,7 @@
4038
*
4139
* @author Mark Paluch
4240
* @author Christoph Strobl
41+
* @author Yanming Zhou
4342
* @since 3.1
4443
*/
4544
public record KeysetScrollSpecification<T> (KeysetScrollPosition position, Sort sort,
@@ -63,21 +62,16 @@ public static Sort createSort(KeysetScrollPosition position, Sort sort, JpaEntit
6362

6463
KeysetScrollDelegate delegate = KeysetScrollDelegate.of(position.getDirection());
6564

66-
Collection<String> sortById;
67-
Sort sortToUse;
68-
if (entity.hasCompositeId()) {
69-
sortById = new ArrayList<>(entity.getIdAttributeNames());
70-
} else {
71-
sortById = new ArrayList<>(1);
72-
sortById.add(entity.getRequiredIdAttribute().getName());
65+
if (sort.isSorted()) {
66+
// assume sort applied on unique property
67+
return delegate.getSortOrders(sort);
7368
}
7469

75-
sort.forEach(it -> sortById.remove(it.getProperty()));
76-
77-
if (sortById.isEmpty()) {
78-
sortToUse = sort;
70+
Sort sortToUse;
71+
if (entity.hasCompositeId()) {
72+
sortToUse = sort.and(Sort.by(entity.getIdAttributeNames().toArray(new String[0])));
7973
} else {
80-
sortToUse = sort.and(Sort.by(sortById.toArray(new String[0])));
74+
sortToUse = sort.and(Sort.by(entity.getRequiredIdAttribute().getName()));
8175
}
8276

8377
return delegate.getSortOrders(sortToUse);

Diff for: spring-data-jpa/src/test/java/org/springframework/data/jpa/repository/query/KeysetScrollSpecificationUnitTests.java

+26-5
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
* Unit tests for {@link KeysetScrollSpecification}.
3737
*
3838
* @author Mark Paluch
39+
* @author Yanming Zhou
3940
*/
4041
@ExtendWith(SpringExtension.class)
4142
@ContextConfiguration({ "classpath:infrastructure.xml" })
@@ -44,24 +45,44 @@ class KeysetScrollSpecificationUnitTests {
4445

4546
@PersistenceContext EntityManager em;
4647

48+
@Test
49+
void shouldUseIdentifierAsFallback() {
50+
51+
Sort sort = KeysetScrollSpecification.createSort(ScrollPosition.keyset(), Sort.unsorted(),
52+
new JpaMetamodelEntityInformation<>(User.class, em.getMetamodel(),
53+
em.getEntityManagerFactory().getPersistenceUnitUtil()));
54+
55+
assertThat(sort).isEqualTo(Sort.by("id"));
56+
}
57+
58+
@Test
59+
void shouldUseCompositeIdentifierAsFallback() {
60+
61+
Sort sort = KeysetScrollSpecification.createSort(ScrollPosition.keyset(), Sort.unsorted(),
62+
new JpaMetamodelEntityInformation<>(SampleWithIdClass.class, em.getMetamodel(),
63+
em.getEntityManagerFactory().getPersistenceUnitUtil()));
64+
65+
assertThat(sort).isEqualTo(Sort.by("first", "second"));
66+
}
67+
4768
@Test // GH-2996
48-
void shouldAddIdentifierToSort() {
69+
void shouldNotAddIdentifierToSort() {
4970

5071
Sort sort = KeysetScrollSpecification.createSort(ScrollPosition.keyset(), Sort.by("firstname"),
5172
new JpaMetamodelEntityInformation<>(User.class, em.getMetamodel(),
5273
em.getEntityManagerFactory().getPersistenceUnitUtil()));
5374

54-
assertThat(sort).extracting(Order::getProperty).containsExactly("firstname", "id");
75+
assertThat(sort).extracting(Order::getProperty).containsExactly("firstname");
5576
}
5677

5778
@Test // GH-2996
58-
void shouldAddCompositeIdentifierToSort() {
79+
void shouldNotAddCompositeIdentifierToSort() {
5980

6081
Sort sort = KeysetScrollSpecification.createSort(ScrollPosition.keyset(), Sort.by("first", "firstname"),
6182
new JpaMetamodelEntityInformation<>(SampleWithIdClass.class, em.getMetamodel(),
6283
em.getEntityManagerFactory().getPersistenceUnitUtil()));
6384

64-
assertThat(sort).extracting(Order::getProperty).containsExactly("first", "firstname", "second");
85+
assertThat(sort).extracting(Order::getProperty).containsExactly("first", "firstname");
6586
}
6687

6788
@Test // GH-2996
@@ -74,4 +95,4 @@ void shouldSkipExistingIdentifiersInSort() {
7495
assertThat(sort).extracting(Order::getProperty).containsExactly("id", "firstname");
7596
}
7697

77-
}
98+
}

0 commit comments

Comments
 (0)