32
32
import org .springframework .data .util .Lazy ;
33
33
import org .springframework .util .Assert ;
34
34
import org .springframework .util .ConcurrentLruCache ;
35
- import org .springframework .util .StringUtils ;
36
35
37
36
/**
38
37
* Base class for {@link String} based JPA queries.
@@ -64,26 +63,42 @@ abstract class AbstractStringBasedJpaQuery extends AbstractJpaQuery {
64
63
* @param method must not be {@literal null}.
65
64
* @param em must not be {@literal null}.
66
65
* @param queryString must not be {@literal null}.
67
- * @param countQueryString must not be {@literal null}.
66
+ * @param countQuery can be {@literal null} if not defined .
68
67
* @param queryConfiguration must not be {@literal null}.
69
68
*/
70
- public AbstractStringBasedJpaQuery (JpaQueryMethod method , EntityManager em , String queryString ,
69
+ AbstractStringBasedJpaQuery (JpaQueryMethod method , EntityManager em , String queryString ,
71
70
@ Nullable String countQueryString , JpaQueryConfiguration queryConfiguration ) {
71
+ this (method , em , method .getDeclaredQuery (queryString ),
72
+ countQueryString != null ? method .getDeclaredQuery (countQueryString ) : null , queryConfiguration );
73
+ }
74
+
75
+ /**
76
+ * Creates a new {@link AbstractStringBasedJpaQuery} from the given {@link JpaQueryMethod}, {@link EntityManager} and
77
+ * query {@link String}.
78
+ *
79
+ * @param method must not be {@literal null}.
80
+ * @param em must not be {@literal null}.
81
+ * @param query must not be {@literal null}.
82
+ * @param countQuery can be {@literal null}.
83
+ * @param queryConfiguration must not be {@literal null}.
84
+ */
85
+ public AbstractStringBasedJpaQuery (JpaQueryMethod method , EntityManager em , DeclaredQuery query ,
86
+ @ Nullable DeclaredQuery countQuery , JpaQueryConfiguration queryConfiguration ) {
72
87
73
88
super (method , em );
74
89
75
- Assert .hasText ( queryString , "Query string must not be null or empty " );
90
+ Assert .notNull ( query , "Query must not be null" );
76
91
Assert .notNull (queryConfiguration , "JpaQueryConfiguration must not be null" );
77
92
78
93
this .valueExpressionDelegate = queryConfiguration .getValueExpressionDelegate ();
79
94
this .valueExpressionContextProvider = valueExpressionDelegate .createValueContextProvider (method .getParameters ());
80
95
81
- this .query = TemplatedQuery .create (queryString , method , queryConfiguration );
96
+ this .query = TemplatedQuery .create (query , method . getEntityInformation () , queryConfiguration );
82
97
83
98
this .countQuery = Lazy .of (() -> {
84
99
85
- if (StringUtils . hasText ( countQueryString ) ) {
86
- return TemplatedQuery .create (countQueryString , method , queryConfiguration );
100
+ if (countQuery != null ) {
101
+ return TemplatedQuery .create (countQuery , method . getEntityInformation () , queryConfiguration );
87
102
}
88
103
89
104
return this .query .deriveCountQuery (method .getCountQueryProjection ());
@@ -119,15 +134,15 @@ public Query doCreateQuery(JpaParametersParameterAccessor accessor) {
119
134
Sort sort = accessor .getSort ();
120
135
ResultProcessor processor = getQueryMethod ().getResultProcessor ().withDynamicProjection (accessor );
121
136
ReturnedType returnedType = processor .getReturnedType ();
122
- QueryProvider sortedQueryString = getSortedQueryString (sort , returnedType );
123
- Query query = createJpaQuery (sortedQueryString , sort , accessor .getPageable (), returnedType );
137
+ QueryProvider sortedQuery = getSortedQuery (sort , returnedType );
138
+ Query query = createJpaQuery (sortedQuery , sort , accessor .getPageable (), returnedType );
124
139
125
140
// it is ok to reuse the binding contained in the ParameterBinder, although we create a new query String because the
126
141
// parameters in the query do not change.
127
142
return parameterBinder .get ().bindAndPrepare (query , accessor );
128
143
}
129
144
130
- QueryProvider getSortedQueryString (Sort sort , ReturnedType returnedType ) {
145
+ QueryProvider getSortedQuery (Sort sort , ReturnedType returnedType ) {
131
146
return querySortRewriter .getSorted (query , sort , returnedType );
132
147
}
133
148
@@ -175,20 +190,20 @@ public StructuredQuery getCountQuery() {
175
190
* Creates an appropriate JPA query from an {@link EntityManager} according to the current {@link AbstractJpaQuery}
176
191
* type.
177
192
*/
178
- protected Query createJpaQuery (QueryProvider queryString , Sort sort , @ Nullable Pageable pageable ,
193
+ protected Query createJpaQuery (QueryProvider query , Sort sort , @ Nullable Pageable pageable ,
179
194
ReturnedType returnedType ) {
180
195
181
196
EntityManager em = getEntityManager ();
182
197
183
198
if (this .query .hasConstructorExpression () || this .query .isDefaultProjection ()) {
184
- return em .createQuery (potentiallyRewriteQuery (queryString .getQueryString (), sort , pageable ));
199
+ return em .createQuery (potentiallyRewriteQuery (query .getQueryString (), sort , pageable ));
185
200
}
186
201
187
202
Class <?> typeToRead = getTypeToRead (returnedType );
188
203
189
204
return typeToRead == null //
190
- ? em .createQuery (potentiallyRewriteQuery (queryString .getQueryString (), sort , pageable )) //
191
- : em .createQuery (potentiallyRewriteQuery (queryString .getQueryString (), sort , pageable ), typeToRead );
205
+ ? em .createQuery (potentiallyRewriteQuery (query .getQueryString (), sort , pageable )) //
206
+ : em .createQuery (potentiallyRewriteQuery (query .getQueryString (), sort , pageable ), typeToRead );
192
207
}
193
208
194
209
/**
@@ -233,21 +248,21 @@ public QueryProvider getSorted(EntityQuery query, Sort sort, ReturnedType return
233
248
234
249
static class UnsortedCachingQuerySortRewriter implements QuerySortRewriter {
235
250
236
- private volatile @ Nullable QueryProvider cachedQueryString ;
251
+ private volatile @ Nullable QueryProvider cachedQuery ;
237
252
238
253
public QueryProvider getSorted (EntityQuery query , Sort sort , ReturnedType returnedType ) {
239
254
240
255
if (sort .isSorted ()) {
241
256
throw new UnsupportedOperationException ("NoOpQueryCache does not support sorting" );
242
257
}
243
258
244
- QueryProvider cachedQueryString = this .cachedQueryString ;
245
- if (cachedQueryString == null ) {
246
- this .cachedQueryString = cachedQueryString = query
259
+ QueryProvider cachedQuery = this .cachedQuery ;
260
+ if (cachedQuery == null ) {
261
+ this .cachedQuery = cachedQuery = query
247
262
.rewrite (new DefaultQueryRewriteInformation (sort , returnedType ));
248
263
}
249
264
250
- return cachedQueryString ;
265
+ return cachedQuery ;
251
266
}
252
267
}
253
268
@@ -259,19 +274,19 @@ class CachingQuerySortRewriter implements QuerySortRewriter {
259
274
private final ConcurrentLruCache <CachableQuery , QueryProvider > queryCache = new ConcurrentLruCache <>(16 ,
260
275
AbstractStringBasedJpaQuery .this ::applySorting );
261
276
262
- private volatile @ Nullable QueryProvider cachedQueryString ;
277
+ private volatile @ Nullable QueryProvider cachedQuery ;
263
278
264
279
@ Override
265
280
public QueryProvider getSorted (EntityQuery query , Sort sort , ReturnedType returnedType ) {
266
281
267
282
if (sort .isUnsorted ()) {
268
283
269
- QueryProvider cachedQueryString = this .cachedQueryString ;
270
- if (cachedQueryString == null ) {
271
- this .cachedQueryString = cachedQueryString = queryCache .get (new CachableQuery (query , sort , returnedType ));
284
+ QueryProvider cachedQuery = this .cachedQuery ;
285
+ if (cachedQuery == null ) {
286
+ this .cachedQuery = cachedQuery = queryCache .get (new CachableQuery (query , sort , returnedType ));
272
287
}
273
288
274
- return cachedQueryString ;
289
+ return cachedQuery ;
275
290
}
276
291
277
292
return queryCache .get (new CachableQuery (query , sort , returnedType ));
0 commit comments