17
17
18
18
import static org .springframework .data .jpa .repository .query .QueryUtils .*;
19
19
20
- import java .util .ArrayList ;
21
20
import java .util .Collection ;
22
- import java .util .Collections ;
23
21
import java .util .Iterator ;
24
22
import java .util .List ;
25
23
26
- import javax .persistence .EntityManager ;
27
24
import javax .persistence .criteria .CriteriaBuilder ;
28
25
import javax .persistence .criteria .CriteriaQuery ;
29
26
import javax .persistence .criteria .Expression ;
32
29
import javax .persistence .criteria .Root ;
33
30
34
31
import org .springframework .data .domain .Sort ;
32
+ import org .springframework .data .jpa .repository .query .ParameterMetadataProvider .ParameterMetadata ;
35
33
import org .springframework .data .mapping .PropertyPath ;
36
- import org .springframework .data .repository .query .Parameter ;
37
- import org .springframework .data .repository .query .Parameters ;
38
34
import org .springframework .data .repository .query .parser .AbstractQueryCreator ;
39
35
import org .springframework .data .repository .query .parser .Part ;
40
36
import org .springframework .data .repository .query .parser .Part .Type ;
41
37
import org .springframework .data .repository .query .parser .PartTree ;
42
38
import org .springframework .util .Assert ;
43
- import org .springframework .util .ClassUtils ;
44
39
45
40
/**
46
41
* Query creator to create a {@link CriteriaQuery} from a {@link PartTree}.
@@ -52,7 +47,7 @@ public class JpaQueryCreator extends AbstractQueryCreator<CriteriaQuery<Object>,
52
47
private final CriteriaBuilder builder ;
53
48
private final Root <?> root ;
54
49
private final CriteriaQuery <Object > query ;
55
- private final ParameterExpressionProvider provider ;
50
+ private final ParameterMetadataProvider provider ;
56
51
57
52
/**
58
53
* Create a new {@link JpaQueryCreator}.
@@ -62,33 +57,29 @@ public class JpaQueryCreator extends AbstractQueryCreator<CriteriaQuery<Object>,
62
57
* @param accessor
63
58
* @param em
64
59
*/
65
- public JpaQueryCreator (PartTree tree , Class <?> domainClass , Parameters parameters , EntityManager em ) {
60
+ public JpaQueryCreator (PartTree tree , Class <?> domainClass , CriteriaBuilder builder ,
61
+ ParameterMetadataProvider provider ) {
66
62
67
63
super (tree );
68
64
69
- this .builder = em . getCriteriaBuilder () ;
65
+ this .builder = builder ;
70
66
this .query = builder .createQuery ().distinct (tree .isDistinct ());
71
67
this .root = query .from (domainClass );
72
- this .provider = new ParameterExpressionProvider ( builder , parameters . getBindableParameters ()) ;
68
+ this .provider = provider ;
73
69
}
74
70
75
71
/**
76
72
* Returns all {@link ParameterExpression} created when creating the query.
77
73
*
78
74
* @return the parameterExpressions
79
75
*/
80
- public List <ParameterExpression <?>> getParameterExpressions () {
81
-
76
+ public List <ParameterMetadata <?>> getParameterExpressions () {
82
77
return provider .getExpressions ();
83
78
}
84
79
85
80
/*
86
81
* (non-Javadoc)
87
- *
88
- * @see
89
- * org.springframework.data.repository.query.parser.AbstractQueryCreator
90
- * #create(org.springframework.data.repository.query.parser.Part,
91
- * java.util.Iterator)
82
+ * @see org.springframework.data.repository.query.parser.AbstractQueryCreator#create(org.springframework.data.repository.query.parser.Part, java.util.Iterator)
92
83
*/
93
84
@ Override
94
85
protected Predicate create (Part part , Iterator <Object > iterator ) {
@@ -98,11 +89,7 @@ protected Predicate create(Part part, Iterator<Object> iterator) {
98
89
99
90
/*
100
91
* (non-Javadoc)
101
- *
102
- * @see
103
- * org.springframework.data.repository.query.parser.AbstractQueryCreator
104
- * #and(org.springframework.data.repository.query.parser.Part,
105
- * java.lang.Object, java.util.Iterator)
92
+ * @see org.springframework.data.repository.query.parser.AbstractQueryCreator#and(org.springframework.data.repository.query.parser.Part, java.lang.Object, java.util.Iterator)
106
93
*/
107
94
@ Override
108
95
protected Predicate and (Part part , Predicate base , Iterator <Object > iterator ) {
@@ -112,10 +99,7 @@ protected Predicate and(Part part, Predicate base, Iterator<Object> iterator) {
112
99
113
100
/*
114
101
* (non-Javadoc)
115
- *
116
- * @see
117
- * org.springframework.data.repository.query.parser.AbstractQueryCreator
118
- * #or(java.lang.Object, java.lang.Object)
102
+ * @see org.springframework.data.repository.query.parser.AbstractQueryCreator#or(java.lang.Object, java.lang.Object)
119
103
*/
120
104
@ Override
121
105
protected Predicate or (Predicate base , Predicate predicate ) {
@@ -146,7 +130,6 @@ protected final CriteriaQuery<Object> complete(Predicate predicate, Sort sort) {
146
130
*/
147
131
protected CriteriaQuery <Object > complete (Predicate predicate , Sort sort , CriteriaQuery <Object > query ,
148
132
CriteriaBuilder builder , Root <?> root ) {
149
-
150
133
return this .query .select (root ).where (predicate ).orderBy (QueryUtils .toOrders (sort , root , builder ));
151
134
}
152
135
@@ -159,7 +142,6 @@ protected CriteriaQuery<Object> complete(Predicate predicate, Sort sort, Criteri
159
142
* @return
160
143
*/
161
144
private Predicate toPredicate (Part part , Root <?> root ) {
162
-
163
145
return new PredicateBuilder (part , root ).build ();
164
146
}
165
147
@@ -180,89 +162,6 @@ private <T> Expression<T> getTypedPath(Root<?> root, Part part, Class<T> type) {
180
162
return toExpressionRecursively (root , part .getProperty ());
181
163
}
182
164
183
- /**
184
- * Helper class to allow easy creation of {@link ParameterExpression}s.
185
- *
186
- * @author Oliver Gierke
187
- */
188
- static class ParameterExpressionProvider {
189
-
190
- private final CriteriaBuilder builder ;
191
- private final Iterator <Parameter > parameters ;
192
- private final List <ParameterExpression <?>> expressions ;
193
-
194
- /**
195
- * Creates a new {@link ParameterExpressionProvider} from the given {@link CriteriaBuilder} and {@link Parameters}.
196
- *
197
- * @param builder
198
- * @param parameters
199
- */
200
- public ParameterExpressionProvider (CriteriaBuilder builder , Parameters parameters ) {
201
-
202
- Assert .notNull (builder );
203
- Assert .notNull (parameters );
204
-
205
- this .builder = builder ;
206
- this .parameters = parameters .iterator ();
207
- this .expressions = new ArrayList <ParameterExpression <?>>();
208
- }
209
-
210
- /**
211
- * Returns all {@link ParameterExpression}s built.
212
- *
213
- * @return the expressions
214
- */
215
- public List <ParameterExpression <?>> getExpressions () {
216
-
217
- return Collections .unmodifiableList (expressions );
218
- }
219
-
220
- /**
221
- * Builds a new {@link ParameterExpression} for the next {@link Parameter}.
222
- *
223
- * @param <T>
224
- * @return
225
- */
226
- @ SuppressWarnings ("unchecked" )
227
- public <T > ParameterExpression <T > next () {
228
-
229
- Parameter parameter = parameters .next ();
230
- return (ParameterExpression <T >) next (parameter .getType (), parameter .getName ());
231
- }
232
-
233
- /**
234
- * Builds a new {@link ParameterExpression} of the given type. Forwards the underlying {@link Parameters} as well.
235
- *
236
- * @param <T>
237
- * @param type must not be {@literal null}.
238
- * @return
239
- */
240
- @ SuppressWarnings ("unchecked" )
241
- public <T > ParameterExpression <? extends T > next (Class <T > type ) {
242
-
243
- Parameter parameter = parameters .next ();
244
- Class <?> typeToUse = ClassUtils .isAssignable (type , parameter .getType ()) ? parameter .getType () : type ;
245
- return (ParameterExpression <? extends T >) next (typeToUse , null );
246
- }
247
-
248
- /**
249
- * Builds a new {@link ParameterExpression} for the given type and name.
250
- *
251
- * @param <T>
252
- * @param type must not be {@literal null}.
253
- * @param name
254
- * @return
255
- */
256
- private <T > ParameterExpression <T > next (Class <T > type , String name ) {
257
-
258
- Assert .notNull (type );
259
-
260
- ParameterExpression <T > expression = name == null ? builder .parameter (type ) : builder .parameter (type , name );
261
- expressions .add (expression );
262
- return expression ;
263
- }
264
- }
265
-
266
165
/**
267
166
* Simple builder to contain logic to create JPA {@link Predicate}s from {@link Part}s.
268
167
*
@@ -300,39 +199,44 @@ public Predicate build() {
300
199
301
200
switch (part .getType ()) {
302
201
case BETWEEN :
303
- ParameterExpression <Comparable > first = provider .next ();
304
- ParameterExpression <Comparable > second = provider .next ();
305
- return builder .between (getComparablePath (root , part ), first , second );
202
+ ParameterMetadata <Comparable > first = provider .next (part );
203
+ ParameterMetadata <Comparable > second = provider .next (part );
204
+ return builder .between (getComparablePath (root , part ), first . getExpression () , second . getExpression () );
306
205
case GREATER_THAN :
307
- return builder .greaterThan (getComparablePath (root , part ), provider .next (Comparable .class ));
206
+ return builder
207
+ .greaterThan (getComparablePath (root , part ), provider .next (part , Comparable .class ).getExpression ());
308
208
case GREATER_THAN_EQUAL :
309
- return builder .greaterThanOrEqualTo (getComparablePath (root , part ), provider .next (Comparable .class ));
209
+ return builder .greaterThanOrEqualTo (getComparablePath (root , part ), provider .next (part , Comparable .class )
210
+ .getExpression ());
310
211
case LESS_THAN :
311
- return builder .lessThan (getComparablePath (root , part ), provider .next (Comparable .class ));
212
+ return builder .lessThan (getComparablePath (root , part ), provider .next (part , Comparable .class ). getExpression ( ));
312
213
case LESS_THAN_EQUAL :
313
- return builder .lessThanOrEqualTo (getComparablePath (root , part ), provider .next (Comparable .class ));
214
+ return builder .lessThanOrEqualTo (getComparablePath (root , part ), provider .next (part , Comparable .class )
215
+ .getExpression ());
314
216
case IS_NULL :
315
217
return path .isNull ();
316
218
case IS_NOT_NULL :
317
219
return path .isNotNull ();
318
220
case NOT_IN :
319
- return path .in (provider .next (Collection .class )).not ();
221
+ return path .in (provider .next (part , Collection .class ). getExpression ( )).not ();
320
222
case IN :
321
- return path .in (provider .next (Collection .class ));
223
+ return path .in (provider .next (part , Collection .class ). getExpression ( ));
322
224
case LIKE :
323
225
case NOT_LIKE :
324
226
Expression <String > propertyExpression = upperIfIgnoreCase (getTypedPath (root , part , String .class ));
325
- Expression <String > parameterExpression = upperIfIgnoreCase (provider .next (String .class ));
227
+ Expression <String > parameterExpression = upperIfIgnoreCase (provider .next (part , String .class ). getExpression ( ));
326
228
Predicate like = builder .like (propertyExpression , parameterExpression );
327
229
return part .getType () == Type .LIKE ? like : like .not ();
328
230
case TRUE :
329
231
return builder .isTrue (getTypedPath (root , part , Boolean .class ));
330
232
case FALSE :
331
233
return builder .isFalse (getTypedPath (root , part , Boolean .class ));
332
234
case SIMPLE_PROPERTY :
333
- return builder .equal (upperIfIgnoreCase (path ), upperIfIgnoreCase (provider .next ()));
235
+ ParameterMetadata <Object > expression = provider .next (part );
236
+ return expression .isIsNullParameter () ? path .isNull () : builder .equal (upperIfIgnoreCase (path ),
237
+ upperIfIgnoreCase (expression .getExpression ()));
334
238
case NEGATING_SIMPLE_PROPERTY :
335
- return builder .notEqual (upperIfIgnoreCase (path ), upperIfIgnoreCase (provider .next ()));
239
+ return builder .notEqual (upperIfIgnoreCase (path ), upperIfIgnoreCase (provider .next (part ). getExpression ( )));
336
240
default :
337
241
throw new IllegalArgumentException ("Unsupported keyword + " + part .getType ());
338
242
}
0 commit comments