@@ -99,10 +99,13 @@ public AbstractStringBasedJpaQuery(JpaQueryMethod method, EntityManager em, Stri
99
99
});
100
100
101
101
this .queryRewriter = queryRewriter ;
102
+ ReturnedType returnedType = method .getResultProcessor ().getReturnedType ();
102
103
103
104
JpaParameters parameters = method .getParameters ();
104
- if (parameters .hasPageableParameter () || parameters .hasSortParameter ()) {
105
+ if (( parameters .hasPageableParameter () || parameters .hasSortParameter ()) && ! parameters . hasDynamicProjection ()) {
105
106
this .querySortRewriter = new CachingQuerySortRewriter ();
107
+ } else if (returnedType .isProjecting () && !returnedType .getReturnedType ().isInterface ()) {
108
+ this .querySortRewriter = new ProjectingSortRewriter ();
106
109
} else {
107
110
this .querySortRewriter = NoOpQuerySortRewriter .INSTANCE ;
108
111
}
@@ -115,9 +118,8 @@ public AbstractStringBasedJpaQuery(JpaQueryMethod method, EntityManager em, Stri
115
118
public Query doCreateQuery (JpaParametersParameterAccessor accessor ) {
116
119
117
120
Sort sort = accessor .getSort ();
118
- String sortedQueryString = getSortedQueryString (sort );
119
-
120
121
ResultProcessor processor = getQueryMethod ().getResultProcessor ().withDynamicProjection (accessor );
122
+ String sortedQueryString = getSortedQueryString (sort , processor .getReturnedType ());
121
123
122
124
Query query = createJpaQuery (sortedQueryString , sort , accessor .getPageable (), processor .getReturnedType ());
123
125
@@ -128,8 +130,8 @@ public Query doCreateQuery(JpaParametersParameterAccessor accessor) {
128
130
return parameterBinder .get ().bindAndPrepare (query , metadata , accessor );
129
131
}
130
132
131
- String getSortedQueryString (Sort sort ) {
132
- return querySortRewriter .getSorted (query , sort );
133
+ String getSortedQueryString (Sort sort , ReturnedType returnedType ) {
134
+ return querySortRewriter .getSorted (query , sort , returnedType );
133
135
}
134
136
135
137
@ Override
@@ -211,24 +213,25 @@ protected String potentiallyRewriteQuery(String originalQuery, Sort sort, @Nulla
211
213
212
214
String applySorting (CachableQuery cachableQuery ) {
213
215
214
- return QueryEnhancerFactory .forQuery (cachableQuery .getDeclaredQuery ()).applySorting (cachableQuery .getSort (),
215
- cachableQuery .getAlias ());
216
+ return QueryEnhancerFactory .forQuery (cachableQuery .getDeclaredQuery ()).rewrite (cachableQuery .getSort (),
217
+ cachableQuery .getReturnedType ());
216
218
}
217
219
218
220
/**
219
221
* Query Sort Rewriter interface.
220
222
*/
221
223
interface QuerySortRewriter {
222
- String getSorted (DeclaredQuery query , Sort sort );
224
+ String getSorted (DeclaredQuery query , Sort sort , ReturnedType returnedType );
223
225
}
224
226
225
227
/**
226
228
* No-op query rewriter.
227
229
*/
228
230
enum NoOpQuerySortRewriter implements QuerySortRewriter {
231
+
229
232
INSTANCE ;
230
233
231
- public String getSorted (DeclaredQuery query , Sort sort ) {
234
+ public String getSorted (DeclaredQuery query , Sort sort , ReturnedType returnedType ) {
232
235
233
236
if (sort .isSorted ()) {
234
237
throw new UnsupportedOperationException ("NoOpQueryCache does not support sorting" );
@@ -238,6 +241,25 @@ public String getSorted(DeclaredQuery query, Sort sort) {
238
241
}
239
242
}
240
243
244
+ static class ProjectingSortRewriter implements QuerySortRewriter {
245
+
246
+ private volatile String cachedQueryString ;
247
+
248
+ public String getSorted (DeclaredQuery query , Sort sort , ReturnedType returnedType ) {
249
+
250
+ if (sort .isSorted ()) {
251
+ throw new UnsupportedOperationException ("NoOpQueryCache does not support sorting" );
252
+ }
253
+
254
+ String cachedQueryString = this .cachedQueryString ;
255
+ if (cachedQueryString == null ) {
256
+ this .cachedQueryString = cachedQueryString = QueryEnhancerFactory .forQuery (query ).rewrite (sort , returnedType );
257
+ }
258
+
259
+ return cachedQueryString ;
260
+ }
261
+ }
262
+
241
263
/**
242
264
* Caching variant of {@link QuerySortRewriter}.
243
265
*/
@@ -246,14 +268,22 @@ class CachingQuerySortRewriter implements QuerySortRewriter {
246
268
private final ConcurrentLruCache <CachableQuery , String > queryCache = new ConcurrentLruCache <>(16 ,
247
269
AbstractStringBasedJpaQuery .this ::applySorting );
248
270
271
+ private volatile String cachedQueryString ;
272
+
249
273
@ Override
250
- public String getSorted (DeclaredQuery query , Sort sort ) {
274
+ public String getSorted (DeclaredQuery query , Sort sort , ReturnedType returnedType ) {
251
275
252
276
if (sort .isUnsorted ()) {
253
- return query .getQueryString ();
277
+
278
+ String cachedQueryString = this .cachedQueryString ;
279
+ if (cachedQueryString == null ) {
280
+ this .cachedQueryString = cachedQueryString = queryCache .get (new CachableQuery (query , sort , returnedType ));
281
+ }
282
+
283
+ return cachedQueryString ;
254
284
}
255
285
256
- return queryCache .get (new CachableQuery (query , sort ));
286
+ return queryCache .get (new CachableQuery (query , sort , returnedType ));
257
287
}
258
288
}
259
289
@@ -269,12 +299,14 @@ static class CachableQuery {
269
299
private final DeclaredQuery declaredQuery ;
270
300
private final String queryString ;
271
301
private final Sort sort ;
302
+ private final ReturnedType returnedType ;
272
303
273
- CachableQuery (DeclaredQuery query , Sort sort ) {
304
+ CachableQuery (DeclaredQuery query , Sort sort , ReturnedType returnedType ) {
274
305
275
306
this .declaredQuery = query ;
276
307
this .queryString = query .getQueryString ();
277
308
this .sort = sort ;
309
+ this .returnedType = returnedType ;
278
310
}
279
311
280
312
DeclaredQuery getDeclaredQuery () {
@@ -285,9 +317,8 @@ Sort getSort() {
285
317
return sort ;
286
318
}
287
319
288
- @ Nullable
289
- String getAlias () {
290
- return declaredQuery .getAlias ();
320
+ public ReturnedType getReturnedType () {
321
+ return returnedType ;
291
322
}
292
323
293
324
@ Override
0 commit comments