Skip to content

Commit af27a15

Browse files
committed
Add support for findBy(…) using Querydsl Predicate that returns a Slice.
Closes #3764
1 parent 1649506 commit af27a15

File tree

3 files changed

+55
-20
lines changed

3 files changed

+55
-20
lines changed

spring-data-jpa/src/main/java/org/springframework/data/jpa/repository/JpaSpecificationExecutor.java

Lines changed: 2 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,6 @@
2828
import org.springframework.dao.InvalidDataAccessApiUsageException;
2929
import org.springframework.data.domain.Page;
3030
import org.springframework.data.domain.Pageable;
31-
import org.springframework.data.domain.Slice;
3231
import org.springframework.data.domain.Sort;
3332
import org.springframework.data.jpa.domain.Specification;
3433
import org.springframework.data.repository.query.FluentQuery;
@@ -182,25 +181,13 @@ default SpecificationFluentQuery<T> project(String... properties) {
182181
@Override
183182
SpecificationFluentQuery<T> project(Collection<String> properties);
184183

185-
/**
186-
* Get a slice of matching elements for {@link Pageable} by requesting {@code Pageable#getPageSize() + 1} elements.
187-
*
188-
* @param pageable the pageable to request a paged result, can be {@link Pageable#unpaged()}, must not be
189-
* {@literal null}. The given {@link Pageable} will override any previously specified {@link Sort sort} if
190-
* the {@link Sort} object is not {@link Sort#isUnsorted()}. Any potentially specified {@link #limit(int)}
191-
* will be overridden by {@link Pageable#getPageSize()}.
192-
* @return
193-
*/
194-
Slice<T> slice(Pageable pageable);
195-
196184
/**
197185
* Get a page of matching elements for {@link Pageable} and provide a custom {@link Specification count
198186
* specification}.
199187
*
200188
* @param pageable the pageable to request a paged result, can be {@link Pageable#unpaged()}, must not be
201-
* {@literal null}. The given {@link Pageable} will override any previously specified {@link Sort sort} if
202-
* the {@link Sort} object is not {@link Sort#isUnsorted()}. Any potentially specified {@link #limit(int)}
203-
* will be overridden by {@link Pageable#getPageSize()}.
189+
* {@literal null}. The given {@link Pageable} will override any previously specified {@link Sort sort}.
190+
* Any potentially specified {@link #limit(int)} will be overridden by {@link Pageable#getPageSize()}.
204191
* @param countSpec specification used to count results.
205192
* @return
206193
*/

spring-data-jpa/src/main/java/org/springframework/data/jpa/repository/support/FetchableFluentQueryByPredicate.java

Lines changed: 35 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@
3131
import org.springframework.data.domain.PageImpl;
3232
import org.springframework.data.domain.Pageable;
3333
import org.springframework.data.domain.ScrollPosition;
34+
import org.springframework.data.domain.Slice;
35+
import org.springframework.data.domain.SliceImpl;
3436
import org.springframework.data.domain.Sort;
3537
import org.springframework.data.domain.Window;
3638
import org.springframework.data.jpa.repository.query.KeysetScrollDelegate;
@@ -191,6 +193,11 @@ public Page<R> page(Pageable pageable) {
191193
return pageable.isUnpaged() ? new PageImpl<>(all(pageable.getSortOr(this.sort))) : readPage(pageable);
192194
}
193195

196+
@Override
197+
public Slice<R> slice(Pageable pageable) {
198+
return pageable.isUnpaged() ? new SliceImpl<>(all(pageable.getSortOr(this.sort))) : readSlice(pageable);
199+
}
200+
194201
@Override
195202
public Stream<R> stream() {
196203

@@ -252,16 +259,40 @@ private void applyQuerySettings(ReturnedType returnedType, int limit, AbstractJP
252259
private Page<R> readPage(Pageable pageable) {
253260

254261
Sort sort = pageable.getSortOr(this.sort);
262+
AbstractJPAQuery<?, ?> query = createQuery(pageable, sort);
263+
264+
List<R> paginatedResults = convert(query.fetch());
265+
266+
return PageableExecutionUtils.getPage(paginatedResults, withSort(pageable, sort),
267+
() -> countOperation.apply(predicate));
268+
}
269+
270+
private Slice<R> readSlice(Pageable pageable) {
271+
272+
Sort sort = pageable.getSortOr(this.sort);
273+
AbstractJPAQuery<?, ?> query = createQuery(pageable, sort);
274+
query.limit(pageable.getPageSize() + 1);
275+
276+
List<?> resultList = query.fetch();
277+
boolean hasNext = resultList.size() > pageable.getPageSize();
278+
if (hasNext) {
279+
resultList = resultList.subList(0, pageable.getPageSize());
280+
}
281+
282+
List<R> slice = convert(resultList);
283+
284+
return new SliceImpl<>(slice, pageable, hasNext);
285+
}
286+
287+
private AbstractJPAQuery<?, ?> createQuery(Pageable pageable, Sort sort) {
288+
255289
AbstractJPAQuery<?, ?> query = pagedFinder.apply(sort, pageable);
256290

257291
if (!properties.isEmpty()) {
258292
query.setHint(EntityGraphFactory.HINT, EntityGraphFactory.create(entityManager, entityType, properties));
259293
}
260294

261-
List<R> paginatedResults = convert(query.fetch());
262-
263-
return PageableExecutionUtils.getPage(paginatedResults, withSort(pageable, sort),
264-
() -> countOperation.apply(predicate));
295+
return query;
265296
}
266297

267298
private List<R> convert(List<?> resultList) {

spring-data-jpa/src/test/java/org/springframework/data/jpa/repository/support/QuerydslJpaPredicateExecutorUnitTests.java

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
import org.springframework.data.domain.Page;
3535
import org.springframework.data.domain.PageRequest;
3636
import org.springframework.data.domain.Pageable;
37+
import org.springframework.data.domain.Slice;
3738
import org.springframework.data.domain.Sort;
3839
import org.springframework.data.domain.Sort.Direction;
3940
import org.springframework.data.domain.Sort.Order;
@@ -399,6 +400,23 @@ void findByFluentPredicatePage() {
399400
assertThat(page1.getContent()).containsExactly(oliver);
400401
}
401402

403+
@Test // GH-3764
404+
void findByFluentPredicateSlice() {
405+
406+
Predicate predicate = user.firstname.contains("v");
407+
408+
Slice<User> slice0 = predicateExecutor.findBy(predicate,
409+
q -> q.sortBy(Sort.by("firstname")).slice(PageRequest.of(0, 1)));
410+
411+
Slice<User> slice1 = predicateExecutor.findBy(predicate,
412+
q -> q.sortBy(Sort.by("firstname")).slice(PageRequest.of(1, 1)));
413+
414+
assertThat(slice0.getContent()).containsExactly(dave);
415+
assertThat(slice0.hasNext()).isTrue();
416+
assertThat(slice1.getContent()).containsExactly(oliver);
417+
assertThat(slice1.hasNext()).isFalse();
418+
}
419+
402420
@Test // GH-3762
403421
void findByFluentPredicateSortOverridePage() {
404422

@@ -409,7 +427,6 @@ void findByFluentPredicateSortOverridePage() {
409427

410428
assertThat(page.getContent()).containsOnly(oliver);
411429
assertThat(predicateExecutor.findAll(predicate, page.nextPageable())).containsOnly(dave);
412-
413430
}
414431

415432
@Test // GH-2294

0 commit comments

Comments
 (0)