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