15
15
*/
16
16
package org .springframework .data .neo4j .repository .query ;
17
17
18
- import java .util .Collection ;
19
- import java .util .List ;
20
- import java .util .function .Function ;
21
- import java .util .function .LongSupplier ;
22
- import java .util .stream .Stream ;
23
-
24
18
import org .apiguardian .api .API ;
19
+ import org .neo4j .cypherdsl .core .Condition ;
25
20
import org .springframework .data .domain .Example ;
21
+ import org .springframework .data .domain .KeysetScrollPosition ;
22
+ import org .springframework .data .domain .OffsetScrollPosition ;
26
23
import org .springframework .data .domain .Page ;
27
24
import org .springframework .data .domain .Pageable ;
25
+ import org .springframework .data .domain .ScrollPosition ;
28
26
import org .springframework .data .domain .Sort ;
27
+ import org .springframework .data .domain .Window ;
29
28
import org .springframework .data .neo4j .core .FluentFindOperation ;
30
29
import org .springframework .data .neo4j .core .mapping .Neo4jMappingContext ;
30
+ import org .springframework .data .neo4j .core .mapping .Neo4jPersistentEntity ;
31
31
import org .springframework .data .repository .query .FluentQuery .FetchableFluentQuery ;
32
32
import org .springframework .data .support .PageableExecutionUtils ;
33
33
import org .springframework .lang .Nullable ;
34
34
35
+ import java .util .Collection ;
36
+ import java .util .List ;
37
+ import java .util .function .Function ;
38
+ import java .util .function .LongSupplier ;
39
+ import java .util .stream .Stream ;
40
+
35
41
/**
36
42
* Immutable implementation of a {@link FetchableFluentQuery}. All
37
43
* methods that return a {@link FetchableFluentQuery} return a new instance, the original instance won't be
@@ -64,7 +70,7 @@ final class FetchableFluentQueryByExample<S, R> extends FluentQuerySupport<R> im
64
70
Function <Example <S >, Boolean > existsOperation
65
71
) {
66
72
this (example , resultType , mappingContext , findOperation , countOperation , existsOperation , Sort .unsorted (),
67
- null );
73
+ null , null );
68
74
}
69
75
70
76
FetchableFluentQueryByExample (
@@ -75,9 +81,10 @@ final class FetchableFluentQueryByExample<S, R> extends FluentQuerySupport<R> im
75
81
Function <Example <S >, Long > countOperation ,
76
82
Function <Example <S >, Boolean > existsOperation ,
77
83
Sort sort ,
84
+ @ Nullable Integer limit ,
78
85
@ Nullable Collection <String > properties
79
86
) {
80
- super (resultType , sort , properties );
87
+ super (resultType , sort , limit , properties );
81
88
this .mappingContext = mappingContext ;
82
89
this .example = example ;
83
90
this .findOperation = findOperation ;
@@ -90,7 +97,14 @@ final class FetchableFluentQueryByExample<S, R> extends FluentQuerySupport<R> im
90
97
public FetchableFluentQuery <R > sortBy (Sort sort ) {
91
98
92
99
return new FetchableFluentQueryByExample <>(this .example , this .resultType , this .mappingContext , this .findOperation ,
93
- this .countOperation , this .existsOperation , this .sort .and (sort ), this .properties );
100
+ this .countOperation , this .existsOperation , this .sort .and (sort ), this .limit , this .properties );
101
+ }
102
+
103
+ @ Override
104
+ @ SuppressWarnings ("HiddenField" )
105
+ public FetchableFluentQuery <R > limit (int limit ) {
106
+ return new FetchableFluentQueryByExample <>(this .example , this .resultType , this .mappingContext , this .findOperation ,
107
+ this .countOperation , this .existsOperation , this .sort , limit , this .properties );
94
108
}
95
109
96
110
@ Override
@@ -106,15 +120,15 @@ public <NR> FetchableFluentQuery<NR> as(Class<NR> resultType) {
106
120
public FetchableFluentQuery <R > project (Collection <String > properties ) {
107
121
108
122
return new FetchableFluentQueryByExample <>(this .example , this .resultType , this .mappingContext , this .findOperation ,
109
- this .countOperation , this .existsOperation , this .sort , mergeProperties (properties ));
123
+ this .countOperation , this .existsOperation , this .sort , this . limit , mergeProperties (properties ));
110
124
}
111
125
112
126
@ Override
113
127
public R oneValue () {
114
128
115
129
return findOperation .find (example .getProbeType ())
116
130
.as (resultType )
117
- .matching (QueryFragmentsAndParameters .forExample (mappingContext , example , sort ,
131
+ .matching (QueryFragmentsAndParameters .forExampleWithSort (mappingContext , example , sort , limit ,
118
132
createIncludedFieldsPredicate ()))
119
133
.oneValue ();
120
134
}
@@ -131,7 +145,7 @@ public List<R> all() {
131
145
132
146
return findOperation .find (example .getProbeType ())
133
147
.as (resultType )
134
- .matching (QueryFragmentsAndParameters .forExample (mappingContext , example , sort ,
148
+ .matching (QueryFragmentsAndParameters .forExampleWithSort (mappingContext , example , sort , limit ,
135
149
createIncludedFieldsPredicate ()))
136
150
.all ();
137
151
}
@@ -141,14 +155,36 @@ public Page<R> page(Pageable pageable) {
141
155
142
156
List <R > page = findOperation .find (example .getProbeType ())
143
157
.as (resultType )
144
- .matching (QueryFragmentsAndParameters .forExample (mappingContext , example , pageable ,
158
+ .matching (QueryFragmentsAndParameters .forExampleWithPageable (mappingContext , example , pageable ,
145
159
createIncludedFieldsPredicate ()))
146
160
.all ();
147
161
148
162
LongSupplier totalCountSupplier = this ::count ;
149
163
return PageableExecutionUtils .getPage (page , pageable , totalCountSupplier );
150
164
}
151
165
166
+ @ Override
167
+ public Window <R > scroll (ScrollPosition scrollPosition ) {
168
+ Class <S > domainType = this .example .getProbeType ();
169
+ Neo4jPersistentEntity <?> entity = mappingContext .getPersistentEntity (domainType );
170
+
171
+ var skip = scrollPosition .isInitial ()
172
+ ? 0
173
+ : (scrollPosition instanceof OffsetScrollPosition offsetScrollPosition ) ? offsetScrollPosition .getOffset ()
174
+ : 0 ;
175
+
176
+ Condition condition = scrollPosition instanceof KeysetScrollPosition keysetScrollPosition
177
+ ? CypherAdapterUtils .combineKeysetIntoCondition (mappingContext .getPersistentEntity (example .getProbeType ()), keysetScrollPosition , sort , mappingContext .getConversionService ())
178
+ : null ;
179
+
180
+ List <R > rawResult = findOperation .find (domainType )
181
+ .as (resultType )
182
+ .matching (QueryFragmentsAndParameters .forExampleWithScrollPosition (mappingContext , example , condition , sort , limit == null ? 1 : limit + 1 , skip , scrollPosition , createIncludedFieldsPredicate ()))
183
+ .all ();
184
+
185
+ return scroll (scrollPosition , rawResult , entity );
186
+ }
187
+
152
188
@ Override
153
189
public Stream <R > stream () {
154
190
return all ().stream ();
0 commit comments