1
1
/*
2
- * Copyright 2008-2012 the original author or authors.
2
+ * Copyright 2008-2015 the original author or authors.
3
3
*
4
4
* Licensed under the Apache License, Version 2.0 (the "License");
5
5
* you may not use this file except in compliance with the License.
25
25
import javax .persistence .criteria .CriteriaBuilder ;
26
26
import javax .persistence .criteria .CriteriaQuery ;
27
27
import javax .persistence .criteria .Expression ;
28
+ import javax .persistence .criteria .Path ;
28
29
import javax .persistence .criteria .Predicate ;
29
30
import javax .persistence .criteria .Root ;
30
31
@@ -147,27 +148,11 @@ private Predicate toPredicate(Part part, Root<?> root) {
147
148
return new PredicateBuilder (part , root ).build ();
148
149
}
149
150
150
- /**
151
- * Returns a path to a {@link Comparable}.
152
- *
153
- * @param root
154
- * @param part
155
- * @return
156
- */
157
- @ SuppressWarnings ({ "rawtypes" })
158
- private Expression <? extends Comparable > getComparablePath (Root <?> root , Part part ) {
159
-
160
- return getTypedPath (root , part );
161
- }
162
-
163
- private <T > Expression <T > getTypedPath (Root <?> root , Part part ) {
164
- return toExpressionRecursively (root , part .getProperty ());
165
- }
166
-
167
151
/**
168
152
* Simple builder to contain logic to create JPA {@link Predicate}s from {@link Part}s.
169
153
*
170
154
* @author Phil Webb
155
+ * @author Oliver Gierke
171
156
*/
172
157
@ SuppressWarnings ({ "unchecked" , "rawtypes" })
173
158
private class PredicateBuilder {
@@ -197,7 +182,6 @@ public PredicateBuilder(Part part, Root<?> root) {
197
182
public Predicate build () {
198
183
199
184
PropertyPath property = part .getProperty ();
200
- Expression <Object > path = toExpressionRecursively (root , property );
201
185
Type type = part .getType ();
202
186
203
187
switch (type ) {
@@ -207,31 +191,41 @@ public Predicate build() {
207
191
return builder .between (getComparablePath (root , part ), first .getExpression (), second .getExpression ());
208
192
case AFTER :
209
193
case GREATER_THAN :
210
- return builder .greaterThan (getComparablePath (root , part ), provider . next ( part , Comparable . class )
211
- .getExpression ());
194
+ return builder .greaterThan (getComparablePath (root , part ),
195
+ provider . next ( part , Comparable . class ) .getExpression ());
212
196
case GREATER_THAN_EQUAL :
213
- return builder .greaterThanOrEqualTo (getComparablePath (root , part ), provider . next ( part , Comparable . class )
214
- .getExpression ());
197
+ return builder .greaterThanOrEqualTo (getComparablePath (root , part ),
198
+ provider . next ( part , Comparable . class ) .getExpression ());
215
199
case BEFORE :
216
200
case LESS_THAN :
217
201
return builder .lessThan (getComparablePath (root , part ), provider .next (part , Comparable .class ).getExpression ());
218
202
case LESS_THAN_EQUAL :
219
- return builder .lessThanOrEqualTo (getComparablePath (root , part ), provider . next ( part , Comparable . class )
220
- .getExpression ());
203
+ return builder .lessThanOrEqualTo (getComparablePath (root , part ),
204
+ provider . next ( part , Comparable . class ) .getExpression ());
221
205
case IS_NULL :
222
- return path .isNull ();
206
+ return getTypedPath ( root , part ) .isNull ();
223
207
case IS_NOT_NULL :
224
- return path .isNotNull ();
208
+ return getTypedPath ( root , part ) .isNotNull ();
225
209
case NOT_IN :
226
- return path .in (provider .next (part , Collection .class ).getExpression ()).not ();
210
+ return getTypedPath ( root , part ) .in (provider .next (part , Collection .class ).getExpression ()).not ();
227
211
case IN :
228
- return path .in (provider .next (part , Collection .class ).getExpression ());
212
+ return getTypedPath ( root , part ) .in (provider .next (part , Collection .class ).getExpression ());
229
213
case STARTING_WITH :
230
214
case ENDING_WITH :
231
215
case CONTAINING :
216
+ case NOT_CONTAINING :
217
+
218
+ if (property .isCollection ()) {
219
+
220
+ Expression <Collection <Object >> propertyExpression = traversePath (root , property );
221
+ Expression <Object > parameterExpression = provider .next (part ).getExpression ();
222
+
223
+ Predicate isMember = builder .isMember (parameterExpression , propertyExpression );
224
+ return type .equals (NOT_CONTAINING ) ? isMember .not () : isMember ;
225
+ }
226
+
232
227
case LIKE :
233
228
case NOT_LIKE :
234
- case NOT_CONTAINING :
235
229
Expression <String > stringPath = getTypedPath (root , part );
236
230
Expression <String > propertyExpression = upperIfIgnoreCase (stringPath );
237
231
Expression <String > parameterExpression = upperIfIgnoreCase (provider .next (part , String .class ).getExpression ());
@@ -245,10 +239,12 @@ public Predicate build() {
245
239
return builder .isFalse (falsePath );
246
240
case SIMPLE_PROPERTY :
247
241
ParameterMetadata <Object > expression = provider .next (part );
248
- return expression .isIsNullParameter () ? path .isNull () : builder .equal (upperIfIgnoreCase (path ),
249
- upperIfIgnoreCase (expression .getExpression ()));
242
+ Expression <Object > path = getTypedPath (root , part );
243
+ return expression .isIsNullParameter () ? path .isNull ()
244
+ : builder .equal (upperIfIgnoreCase (path ), upperIfIgnoreCase (expression .getExpression ()));
250
245
case NEGATING_SIMPLE_PROPERTY :
251
- return builder .notEqual (upperIfIgnoreCase (path ), upperIfIgnoreCase (provider .next (part ).getExpression ()));
246
+ return builder .notEqual (upperIfIgnoreCase (getTypedPath (root , part )),
247
+ upperIfIgnoreCase (provider .next (part ).getExpression ()));
252
248
default :
253
249
throw new IllegalArgumentException ("Unsupported keyword " + type );
254
250
}
@@ -287,5 +283,26 @@ private <T> Expression<T> upperIfIgnoreCase(Expression<? extends T> expression)
287
283
private boolean canUpperCase (Expression <?> expression ) {
288
284
return String .class .equals (expression .getJavaType ());
289
285
}
286
+
287
+ /**
288
+ * Returns a path to a {@link Comparable}.
289
+ *
290
+ * @param root
291
+ * @param part
292
+ * @return
293
+ */
294
+ private Expression <? extends Comparable > getComparablePath (Root <?> root , Part part ) {
295
+ return getTypedPath (root , part );
296
+ }
297
+
298
+ private <T > Expression <T > getTypedPath (Root <?> root , Part part ) {
299
+ return toExpressionRecursively (root , part .getProperty ());
300
+ }
301
+
302
+ private <T > Expression <T > traversePath (Path <?> root , PropertyPath path ) {
303
+
304
+ Path <Object > result = root .get (path .getSegment ());
305
+ return (Expression <T >) (path .hasNext () ? traversePath (result , path .next ()) : result );
306
+ }
290
307
}
291
308
}
0 commit comments