17
17
18
18
import java .util .ArrayList ;
19
19
import java .util .Collection ;
20
+ import java .util .Collections ;
20
21
import java .util .List ;
21
22
import java .util .function .Function ;
22
23
import java .util .stream .Stream ;
36
37
import org .springframework .data .mapping .context .MappingContext ;
37
38
import org .springframework .data .repository .query .FluentQuery .FetchableFluentQuery ;
38
39
import org .springframework .data .support .PageableExecutionUtils ;
39
- import org .springframework .lang .Nullable ;
40
40
import org .springframework .util .Assert ;
41
41
42
42
/**
47
47
* @param <R> Result type
48
48
* @author Greg Turnquist
49
49
* @author Mark Paluch
50
+ * @author Jens Schauder
50
51
* @since 2.6
51
52
*/
52
- class FetchableFluentQueryByExample <S , R > extends FluentQuerySupport <R > implements FetchableFluentQuery <R > {
53
+ class FetchableFluentQueryByExample <S , R > extends FluentQuerySupport <S , R > implements FetchableFluentQuery <R > {
53
54
54
55
private final Example <S > example ;
55
56
private final Function <Sort , TypedQuery <S >> finder ;
56
57
private final Function <Example <S >, Long > countOperation ;
57
58
private final Function <Example <S >, Boolean > existsOperation ;
58
59
private final EntityManager entityManager ;
59
60
private final EscapeCharacter escapeCharacter ;
61
+ private final Projector <TypedQuery <?>> projector ;
60
62
61
63
public FetchableFluentQueryByExample (Example <S > example , Function <Sort , TypedQuery <S >> finder ,
62
64
Function <Example <S >, Long > countOperation , Function <Example <S >, Boolean > existsOperation ,
63
65
MappingContext <? extends PersistentEntity <?, ?>, ? extends PersistentProperty <?>> context ,
64
66
EntityManager entityManager , EscapeCharacter escapeCharacter ) {
65
- this (example , (Class <R >) example .getProbeType (), Sort .unsorted (), null , finder , countOperation , existsOperation ,
66
- context , entityManager , escapeCharacter );
67
+ this (example , example .getProbeType (), (Class <R >) example .getProbeType (), Sort .unsorted (), Collections .emptySet (),
68
+ finder , countOperation , existsOperation , context , entityManager , escapeCharacter ,
69
+ new TypedQueryProjector (entityManager ));
67
70
}
68
71
69
- private FetchableFluentQueryByExample (Example <S > example , Class <R > returnType , Sort sort ,
70
- @ Nullable Collection <String > properties , Function <Sort , TypedQuery <S >> finder ,
71
- Function <Example <S >, Long > countOperation , Function < Example < S >, Boolean > existsOperation ,
72
+ private FetchableFluentQueryByExample (Example <S > example , Class <S > entityType , Class < R > returnType , Sort sort ,
73
+ Collection <String > properties , Function <Sort , TypedQuery <S >> finder , Function < Example < S >, Long > countOperation ,
74
+ Function <Example <S >, Boolean > existsOperation ,
72
75
MappingContext <? extends PersistentEntity <?, ?>, ? extends PersistentProperty <?>> context ,
73
- EntityManager entityManager , EscapeCharacter escapeCharacter ) {
76
+ EntityManager entityManager , EscapeCharacter escapeCharacter , Projector < TypedQuery <?>> projector ) {
74
77
75
- super (returnType , sort , properties , context );
78
+ super (returnType , sort , properties , context , entityType );
76
79
this .example = example ;
77
80
this .finder = finder ;
78
81
this .countOperation = countOperation ;
79
82
this .existsOperation = existsOperation ;
80
83
this .entityManager = entityManager ;
81
84
this .escapeCharacter = escapeCharacter ;
85
+ this .projector = projector ;
82
86
}
83
87
84
88
/*
@@ -90,8 +94,9 @@ public FetchableFluentQuery<R> sortBy(Sort sort) {
90
94
91
95
Assert .notNull (sort , "Sort must not be null!" );
92
96
93
- return new FetchableFluentQueryByExample <>(this .example , this .resultType , this .sort .and (sort ), this .properties ,
94
- this .finder , this .countOperation , this .existsOperation , this .context , this .entityManager , this .escapeCharacter );
97
+ return new FetchableFluentQueryByExample <>(example , entityType , resultType , sort .and (sort ), properties , finder ,
98
+ countOperation , existsOperation , context , entityManager , escapeCharacter ,
99
+ new TypedQueryProjector (entityManager ));
95
100
}
96
101
97
102
/*
@@ -106,8 +111,9 @@ public <NR> FetchableFluentQuery<NR> as(Class<NR> resultType) {
106
111
throw new UnsupportedOperationException ("Class-based DTOs are not yet supported." );
107
112
}
108
113
109
- return new FetchableFluentQueryByExample <>(this .example , resultType , this .sort , this .properties , this .finder ,
110
- this .countOperation , this .existsOperation , this .context , this .entityManager , this .escapeCharacter );
114
+ return new FetchableFluentQueryByExample <>(example , entityType , resultType , sort , properties , finder ,
115
+ countOperation , existsOperation , context , entityManager , escapeCharacter ,
116
+ new TypedQueryProjector (entityManager ));
111
117
}
112
118
113
119
/*
@@ -117,8 +123,9 @@ public <NR> FetchableFluentQuery<NR> as(Class<NR> resultType) {
117
123
@ Override
118
124
public FetchableFluentQuery <R > project (Collection <String > properties ) {
119
125
120
- return new FetchableFluentQueryByExample <>(this .example , this .resultType , this .sort , mergeProperties (properties ),
121
- this .finder , this .countOperation , this .existsOperation , this .context , this .entityManager , this .escapeCharacter );
126
+ return new FetchableFluentQueryByExample <>(example , entityType , resultType , sort , mergeProperties (properties ),
127
+ finder , countOperation , existsOperation , context , entityManager , escapeCharacter ,
128
+ new TypedQueryProjector (entityManager ));
122
129
}
123
130
124
131
/*
@@ -128,7 +135,7 @@ public FetchableFluentQuery<R> project(Collection<String> properties) {
128
135
@ Override
129
136
public R oneValue () {
130
137
131
- TypedQuery <S > limitedQuery = this . finder . apply ( this . sort );
138
+ TypedQuery <S > limitedQuery = createSortedAndProjectedQuery ( );
132
139
limitedQuery .setMaxResults (2 ); // Never need more than 2 values
133
140
134
141
List <S > results = limitedQuery .getResultList ();
@@ -147,7 +154,7 @@ public R oneValue() {
147
154
@ Override
148
155
public R firstValue () {
149
156
150
- TypedQuery <S > limitedQuery = this . finder . apply ( this . sort );
157
+ TypedQuery <S > limitedQuery = createSortedAndProjectedQuery ( );
151
158
limitedQuery .setMaxResults (1 ); // Never need more than 1 value
152
159
153
160
List <S > results = limitedQuery .getResultList ();
@@ -162,7 +169,7 @@ public R firstValue() {
162
169
@ Override
163
170
public List <R > all () {
164
171
165
- List <S > resultList = this . finder . apply ( this . sort ).getResultList ();
172
+ List <S > resultList = createSortedAndProjectedQuery ( ).getResultList ();
166
173
167
174
return convert (resultList );
168
175
}
@@ -183,7 +190,7 @@ public Page<R> page(Pageable pageable) {
183
190
@ Override
184
191
public Stream <R > stream () {
185
192
186
- return this . finder . apply ( this . sort ) //
193
+ return createSortedAndProjectedQuery ( ) //
187
194
.getResultStream () //
188
195
.map (getConversionFunction ());
189
196
}
@@ -194,7 +201,7 @@ public Stream<R> stream() {
194
201
*/
195
202
@ Override
196
203
public long count () {
197
- return this . countOperation .apply (example );
204
+ return countOperation .apply (example );
198
205
}
199
206
200
207
/*
@@ -203,12 +210,12 @@ public long count() {
203
210
*/
204
211
@ Override
205
212
public boolean exists () {
206
- return this . existsOperation .apply (example );
213
+ return existsOperation .apply (example );
207
214
}
208
215
209
216
private Page <R > readPage (Pageable pageable ) {
210
217
211
- TypedQuery <S > pagedQuery = this . finder . apply ( this . sort );
218
+ TypedQuery <S > pagedQuery = createSortedAndProjectedQuery ( );
212
219
213
220
if (pageable .isPaged ()) {
214
221
pagedQuery .setFirstResult ((int ) pageable .getOffset ());
@@ -217,7 +224,15 @@ private Page<R> readPage(Pageable pageable) {
217
224
218
225
List <R > paginatedResults = convert (pagedQuery .getResultList ());
219
226
220
- return PageableExecutionUtils .getPage (paginatedResults , pageable , () -> this .countOperation .apply (this .example ));
227
+ return PageableExecutionUtils .getPage (paginatedResults , pageable , () -> countOperation .apply (example ));
228
+ }
229
+
230
+ private TypedQuery <S > createSortedAndProjectedQuery () {
231
+
232
+ TypedQuery <S > query = finder .apply (sort );
233
+ projector .apply (entityType , query , properties );
234
+
235
+ return query ;
221
236
}
222
237
223
238
private List <R > convert (List <S > resultList ) {
@@ -232,7 +247,7 @@ private List<R> convert(List<S> resultList) {
232
247
}
233
248
234
249
private Function <Object , R > getConversionFunction () {
235
- return getConversionFunction (this . example .getProbeType (), this . resultType );
250
+ return getConversionFunction (example .getProbeType (), resultType );
236
251
}
237
252
238
253
}
0 commit comments