Skip to content

Commit 8c3f052

Browse files
committed
Add support for scroll API using Querydsl and Query by Example repositories.
1 parent a1beddb commit 8c3f052

File tree

10 files changed

+192
-50
lines changed

10 files changed

+192
-50
lines changed

spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/FetchableFluentQuerySupport.java

Lines changed: 25 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -33,17 +33,21 @@ abstract class FetchableFluentQuerySupport<P, T> implements FluentQuery.Fetchabl
3333

3434
private final P predicate;
3535
private final Sort sort;
36+
37+
private final int limit;
38+
3639
private final Class<T> resultType;
3740
private final List<String> fieldsToInclude;
3841

39-
FetchableFluentQuerySupport(P predicate, Sort sort, Class<T> resultType, List<String> fieldsToInclude) {
42+
FetchableFluentQuerySupport(P predicate, Sort sort, int limit, Class<T> resultType, List<String> fieldsToInclude) {
4043
this.predicate = predicate;
4144
this.sort = sort;
45+
this.limit = limit;
4246
this.resultType = resultType;
4347
this.fieldsToInclude = fieldsToInclude;
4448
}
4549

46-
/*
50+
/*
4751
* (non-Javadoc)
4852
* @see org.springframework.data.repository.query.FluentQuery.FetchableFluentQuery#sortBy(org.springframework.data.domain.Sort)
4953
*/
@@ -52,10 +56,18 @@ public FluentQuery.FetchableFluentQuery<T> sortBy(Sort sort) {
5256

5357
Assert.notNull(sort, "Sort must not be null");
5458

55-
return create(predicate, sort, resultType, fieldsToInclude);
59+
return create(predicate, sort, limit, resultType, fieldsToInclude);
5660
}
5761

58-
/*
62+
@Override
63+
public FluentQuery.FetchableFluentQuery<T> limit(int limit) {
64+
65+
Assert.isTrue(limit > 0, "Limit must be greater zero");
66+
67+
return create(predicate, sort, limit, resultType, fieldsToInclude);
68+
}
69+
70+
/*
5971
* (non-Javadoc)
6072
* @see org.springframework.data.repository.query.FluentQuery.FetchableFluentQuery#as(java.lang.Class)
6173
*/
@@ -64,10 +76,10 @@ public <R> FluentQuery.FetchableFluentQuery<R> as(Class<R> projection) {
6476

6577
Assert.notNull(projection, "Projection target type must not be null");
6678

67-
return create(predicate, sort, projection, fieldsToInclude);
79+
return create(predicate, sort, limit, projection, fieldsToInclude);
6880
}
6981

70-
/*
82+
/*
7183
* (non-Javadoc)
7284
* @see org.springframework.data.repository.query.FluentQuery.FetchableFluentQuery#project(java.util.Collection)
7385
*/
@@ -76,11 +88,11 @@ public FluentQuery.FetchableFluentQuery<T> project(Collection<String> properties
7688

7789
Assert.notNull(properties, "Projection properties must not be null");
7890

79-
return create(predicate, sort, resultType, new ArrayList<>(properties));
91+
return create(predicate, sort, limit, resultType, new ArrayList<>(properties));
8092
}
8193

82-
protected abstract <R> FetchableFluentQuerySupport<P, R> create(P predicate, Sort sort, Class<R> resultType,
83-
List<String> fieldsToInclude);
94+
protected abstract <R> FetchableFluentQuerySupport<P, R> create(P predicate, Sort sort, int limit,
95+
Class<R> resultType, List<String> fieldsToInclude);
8496

8597
P getPredicate() {
8698
return predicate;
@@ -90,6 +102,10 @@ Sort getSort() {
90102
return sort;
91103
}
92104

105+
int getLimit() {
106+
return limit;
107+
}
108+
93109
Class<T> getResultType() {
94110
return resultType;
95111
}

spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/QuerydslMongoPredicateExecutor.java

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@
2525
import org.springframework.dao.IncorrectResultSizeDataAccessException;
2626
import org.springframework.data.domain.Page;
2727
import org.springframework.data.domain.Pageable;
28+
import org.springframework.data.domain.Scroll;
29+
import org.springframework.data.domain.ScrollPosition;
2830
import org.springframework.data.domain.Sort;
2931
import org.springframework.data.mongodb.core.MongoOperations;
3032
import org.springframework.data.mongodb.core.query.BasicQuery;
@@ -228,17 +230,17 @@ private SpringDataMongodbQuery<T> applySorting(SpringDataMongodbQuery<T> query,
228230
class FluentQuerydsl<T> extends FetchableFluentQuerySupport<Predicate, T> {
229231

230232
FluentQuerydsl(Predicate predicate, Class<T> resultType) {
231-
this(predicate, Sort.unsorted(), resultType, Collections.emptyList());
233+
this(predicate, Sort.unsorted(), 0, resultType, Collections.emptyList());
232234
}
233235

234-
FluentQuerydsl(Predicate predicate, Sort sort, Class<T> resultType, List<String> fieldsToInclude) {
235-
super(predicate, sort, resultType, fieldsToInclude);
236+
FluentQuerydsl(Predicate predicate, Sort sort, int limit, Class<T> resultType, List<String> fieldsToInclude) {
237+
super(predicate, sort, limit, resultType, fieldsToInclude);
236238
}
237239

238240
@Override
239-
protected <R> FluentQuerydsl<R> create(Predicate predicate, Sort sort, Class<R> resultType,
241+
protected <R> FluentQuerydsl<R> create(Predicate predicate, Sort sort, int limit, Class<R> resultType,
240242
List<String> fieldsToInclude) {
241-
return new FluentQuerydsl<>(predicate, sort, resultType, fieldsToInclude);
243+
return new FluentQuerydsl<>(predicate, sort, limit, resultType, fieldsToInclude);
242244
}
243245

244246
@Override
@@ -256,6 +258,11 @@ public List<T> all() {
256258
return createQuery().fetch();
257259
}
258260

261+
@Override
262+
public Scroll<T> scroll(ScrollPosition scrollPosition) {
263+
return createQuery().scroll(scrollPosition);
264+
}
265+
259266
@Override
260267
public Page<T> page(Pageable pageable) {
261268

@@ -296,6 +303,8 @@ private void customize(BasicQuery query) {
296303
if (getSort().isSorted()) {
297304
query.with(getSort());
298305
}
306+
307+
query.limit(getLimit());
299308
}
300309
}
301310
}

spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/ReactiveFluentQuerySupport.java

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -33,12 +33,14 @@ abstract class ReactiveFluentQuerySupport<P, T> implements FluentQuery.ReactiveF
3333

3434
private final P predicate;
3535
private final Sort sort;
36+
private final int limit;
3637
private final Class<T> resultType;
3738
private final List<String> fieldsToInclude;
3839

39-
ReactiveFluentQuerySupport(P predicate, Sort sort, Class<T> resultType, List<String> fieldsToInclude) {
40+
ReactiveFluentQuerySupport(P predicate, Sort sort, int limit, Class<T> resultType, List<String> fieldsToInclude) {
4041
this.predicate = predicate;
4142
this.sort = sort;
43+
this.limit = limit;
4244
this.resultType = resultType;
4345
this.fieldsToInclude = fieldsToInclude;
4446
}
@@ -52,7 +54,15 @@ public ReactiveFluentQuery<T> sortBy(Sort sort) {
5254

5355
Assert.notNull(sort, "Sort must not be null");
5456

55-
return create(predicate, sort, resultType, fieldsToInclude);
57+
return create(predicate, sort, limit, resultType, fieldsToInclude);
58+
}
59+
60+
@Override
61+
public ReactiveFluentQuery<T> limit(int limit) {
62+
63+
Assert.isTrue(limit > 0, "Limit must be greater zero");
64+
65+
return create(predicate, sort, limit, resultType, fieldsToInclude);
5666
}
5767

5868
/*
@@ -64,7 +74,7 @@ public <R> ReactiveFluentQuery<R> as(Class<R> projection) {
6474

6575
Assert.notNull(projection, "Projection target type must not be null");
6676

67-
return create(predicate, sort, projection, fieldsToInclude);
77+
return create(predicate, sort, limit, projection, fieldsToInclude);
6878
}
6979

7080
/*
@@ -76,10 +86,10 @@ public ReactiveFluentQuery<T> project(Collection<String> properties) {
7686

7787
Assert.notNull(properties, "Projection properties must not be null");
7888

79-
return create(predicate, sort, resultType, new ArrayList<>(properties));
89+
return create(predicate, sort, limit, resultType, new ArrayList<>(properties));
8090
}
8191

82-
protected abstract <R> ReactiveFluentQuerySupport<P, R> create(P predicate, Sort sort, Class<R> resultType,
92+
protected abstract <R> ReactiveFluentQuerySupport<P, R> create(P predicate, Sort sort, int limit, Class<R> resultType,
8393
List<String> fieldsToInclude);
8494

8595
P getPredicate() {
@@ -90,6 +100,10 @@ Sort getSort() {
90100
return sort;
91101
}
92102

103+
int getLimit() {
104+
return limit;
105+
}
106+
93107
Class<T> getResultType() {
94108
return resultType;
95109
}

spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/ReactiveQuerydslMongoPredicateExecutor.java

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@
2626
import org.reactivestreams.Publisher;
2727
import org.springframework.data.domain.Page;
2828
import org.springframework.data.domain.Pageable;
29+
import org.springframework.data.domain.Scroll;
30+
import org.springframework.data.domain.ScrollPosition;
2931
import org.springframework.data.domain.Sort;
3032
import org.springframework.data.mongodb.core.ReactiveMongoOperations;
3133
import org.springframework.data.mongodb.core.query.BasicQuery;
@@ -195,17 +197,18 @@ private ReactiveSpringDataMongodbQuery<T> applySorting(ReactiveSpringDataMongodb
195197
class ReactiveFluentQuerydsl<T> extends ReactiveFluentQuerySupport<Predicate, T> {
196198

197199
ReactiveFluentQuerydsl(Predicate predicate, Class<T> resultType) {
198-
this(predicate, Sort.unsorted(), resultType, Collections.emptyList());
200+
this(predicate, Sort.unsorted(), 0, resultType, Collections.emptyList());
199201
}
200202

201-
ReactiveFluentQuerydsl(Predicate predicate, Sort sort, Class<T> resultType, List<String> fieldsToInclude) {
202-
super(predicate, sort, resultType, fieldsToInclude);
203+
ReactiveFluentQuerydsl(Predicate predicate, Sort sort, int limit, Class<T> resultType,
204+
List<String> fieldsToInclude) {
205+
super(predicate, sort, limit, resultType, fieldsToInclude);
203206
}
204207

205208
@Override
206-
protected <R> ReactiveFluentQuerydsl<R> create(Predicate predicate, Sort sort, Class<R> resultType,
209+
protected <R> ReactiveFluentQuerydsl<R> create(Predicate predicate, Sort sort, int limit, Class<R> resultType,
207210
List<String> fieldsToInclude) {
208-
return new ReactiveFluentQuerydsl<>(predicate, sort, resultType, fieldsToInclude);
211+
return new ReactiveFluentQuerydsl<>(predicate, sort, limit, resultType, fieldsToInclude);
209212
}
210213

211214
@Override
@@ -223,6 +226,11 @@ public Flux<T> all() {
223226
return createQuery().fetch();
224227
}
225228

229+
@Override
230+
public Mono<Scroll<T>> scroll(ScrollPosition scrollPosition) {
231+
return createQuery().scroll(scrollPosition);
232+
}
233+
226234
@Override
227235
public Mono<Page<T>> page(Pageable pageable) {
228236

@@ -260,6 +268,8 @@ private void customize(BasicQuery query) {
260268
if (getSort().isSorted()) {
261269
query.with(getSort());
262270
}
271+
272+
query.limit(getLimit());
263273
}
264274
}
265275

spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/ReactiveSpringDataMongodbQuery.java

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,10 @@
2424
import java.util.function.Consumer;
2525

2626
import org.bson.Document;
27-
2827
import org.springframework.data.domain.Page;
2928
import org.springframework.data.domain.Pageable;
29+
import org.springframework.data.domain.Scroll;
30+
import org.springframework.data.domain.ScrollPosition;
3031
import org.springframework.data.mongodb.core.MongoOperations;
3132
import org.springframework.data.mongodb.core.ReactiveFindOperation;
3233
import org.springframework.data.mongodb.core.ReactiveMongoOperations;
@@ -90,15 +91,19 @@ Flux<K> fetch() {
9091
return createQuery().flatMapMany(it -> find.matching(it).all());
9192
}
9293

94+
Mono<Scroll<K>> scroll(ScrollPosition scrollPosition) {
95+
return createQuery().flatMap(it -> find.matching(it).scroll(scrollPosition));
96+
}
97+
9398
/**
9499
* Fetch all matching query results as page.
95100
*
96101
* @return {@link Mono} emitting the requested page.
97102
*/
98103
Mono<Page<K>> fetchPage(Pageable pageable) {
99104

100-
Mono<List<K>> content = createQuery().map(it -> it.with(pageable))
101-
.flatMapMany(it -> find.matching(it).all()).collectList();
105+
Mono<List<K>> content = createQuery().map(it -> it.with(pageable)).flatMapMany(it -> find.matching(it).all())
106+
.collectList();
102107

103108
return content.flatMap(it -> ReactivePageableExecutionUtils.getPage(it, pageable, fetchCount()));
104109
}

spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/SimpleMongoRepository.java

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,8 @@
3232
import org.springframework.data.domain.Page;
3333
import org.springframework.data.domain.PageImpl;
3434
import org.springframework.data.domain.Pageable;
35+
import org.springframework.data.domain.Scroll;
36+
import org.springframework.data.domain.ScrollPosition;
3537
import org.springframework.data.domain.Sort;
3638
import org.springframework.data.mongodb.core.ExecutableFindOperation;
3739
import org.springframework.data.mongodb.core.MongoOperations;
@@ -361,17 +363,17 @@ private List<T> findAll(@Nullable Query query) {
361363
class FluentQueryByExample<S, T> extends FetchableFluentQuerySupport<Example<S>, T> {
362364

363365
FluentQueryByExample(Example<S> example, Class<T> resultType) {
364-
this(example, Sort.unsorted(), resultType, Collections.emptyList());
366+
this(example, Sort.unsorted(), 0, resultType, Collections.emptyList());
365367
}
366368

367-
FluentQueryByExample(Example<S> example, Sort sort, Class<T> resultType, List<String> fieldsToInclude) {
368-
super(example, sort, resultType, fieldsToInclude);
369+
FluentQueryByExample(Example<S> example, Sort sort, int limit, Class<T> resultType, List<String> fieldsToInclude) {
370+
super(example, sort, limit, resultType, fieldsToInclude);
369371
}
370372

371373
@Override
372-
protected <R> FluentQueryByExample<S, R> create(Example<S> predicate, Sort sort, Class<R> resultType,
374+
protected <R> FluentQueryByExample<S, R> create(Example<S> predicate, Sort sort, int limit, Class<R> resultType,
373375
List<String> fieldsToInclude) {
374-
return new FluentQueryByExample<>(predicate, sort, resultType, fieldsToInclude);
376+
return new FluentQueryByExample<>(predicate, sort, limit, resultType, fieldsToInclude);
375377
}
376378

377379
@Override
@@ -389,6 +391,11 @@ public List<T> all() {
389391
return createQuery().all();
390392
}
391393

394+
@Override
395+
public Scroll<T> scroll(ScrollPosition scrollPosition) {
396+
return createQuery().scroll(scrollPosition);
397+
}
398+
392399
@Override
393400
public Page<T> page(Pageable pageable) {
394401

@@ -427,6 +434,8 @@ private ExecutableFindOperation.TerminatingFind<T> createQuery(UnaryOperator<Que
427434
query.with(getSort());
428435
}
429436

437+
query.limit(getLimit());
438+
430439
if (!getFieldsToInclude().isEmpty()) {
431440
query.fields().include(getFieldsToInclude().toArray(new String[0]));
432441
}

spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/SimpleReactiveMongoRepository.java

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,8 @@
3434
import org.springframework.data.domain.Example;
3535
import org.springframework.data.domain.Page;
3636
import org.springframework.data.domain.Pageable;
37+
import org.springframework.data.domain.Scroll;
38+
import org.springframework.data.domain.ScrollPosition;
3739
import org.springframework.data.domain.Sort;
3840
import org.springframework.data.mongodb.core.ReactiveFindOperation;
3941
import org.springframework.data.mongodb.core.ReactiveMongoOperations;
@@ -404,17 +406,18 @@ private Flux<T> findAll(Query query) {
404406
class ReactiveFluentQueryByExample<S, T> extends ReactiveFluentQuerySupport<Example<S>, T> {
405407

406408
ReactiveFluentQueryByExample(Example<S> example, Class<T> resultType) {
407-
this(example, Sort.unsorted(), resultType, Collections.emptyList());
409+
this(example, Sort.unsorted(), 0, resultType, Collections.emptyList());
408410
}
409411

410-
ReactiveFluentQueryByExample(Example<S> example, Sort sort, Class<T> resultType, List<String> fieldsToInclude) {
411-
super(example, sort, resultType, fieldsToInclude);
412+
ReactiveFluentQueryByExample(Example<S> example, Sort sort, int limit, Class<T> resultType,
413+
List<String> fieldsToInclude) {
414+
super(example, sort, limit, resultType, fieldsToInclude);
412415
}
413416

414417
@Override
415-
protected <R> ReactiveFluentQueryByExample<S, R> create(Example<S> predicate, Sort sort, Class<R> resultType,
416-
List<String> fieldsToInclude) {
417-
return new ReactiveFluentQueryByExample<>(predicate, sort, resultType, fieldsToInclude);
418+
protected <R> ReactiveFluentQueryByExample<S, R> create(Example<S> predicate, Sort sort, int limit,
419+
Class<R> resultType, List<String> fieldsToInclude) {
420+
return new ReactiveFluentQueryByExample<>(predicate, sort, limit, resultType, fieldsToInclude);
418421
}
419422

420423
@Override
@@ -432,6 +435,11 @@ public Flux<T> all() {
432435
return createQuery().all();
433436
}
434437

438+
@Override
439+
public Mono<Scroll<T>> scroll(ScrollPosition scrollPosition) {
440+
return createQuery().scroll(scrollPosition);
441+
}
442+
435443
@Override
436444
public Mono<Page<T>> page(Pageable pageable) {
437445

@@ -465,6 +473,8 @@ private ReactiveFindOperation.TerminatingFind<T> createQuery(UnaryOperator<Query
465473
query.with(getSort());
466474
}
467475

476+
query.limit(getLimit());
477+
468478
if (!getFieldsToInclude().isEmpty()) {
469479
query.fields().include(getFieldsToInclude().toArray(new String[0]));
470480
}

0 commit comments

Comments
 (0)