1717
1818import static org .springframework .data .jpa .repository .query .QueryUtils .*;
1919
20- import java .util .ArrayList ;
2120import java .util .Collection ;
22- import java .util .Collections ;
2321import java .util .Iterator ;
2422import java .util .List ;
2523
26- import javax .persistence .EntityManager ;
2724import javax .persistence .criteria .CriteriaBuilder ;
2825import javax .persistence .criteria .CriteriaQuery ;
2926import javax .persistence .criteria .Expression ;
3229import javax .persistence .criteria .Root ;
3330
3431import org .springframework .data .domain .Sort ;
32+ import org .springframework .data .jpa .repository .query .ParameterMetadataProvider .ParameterMetadata ;
3533import org .springframework .data .mapping .PropertyPath ;
36- import org .springframework .data .repository .query .Parameter ;
37- import org .springframework .data .repository .query .Parameters ;
3834import org .springframework .data .repository .query .parser .AbstractQueryCreator ;
3935import org .springframework .data .repository .query .parser .Part ;
4036import org .springframework .data .repository .query .parser .Part .Type ;
4137import org .springframework .data .repository .query .parser .PartTree ;
4238import org .springframework .util .Assert ;
43- import org .springframework .util .ClassUtils ;
4439
4540/**
4641 * Query creator to create a {@link CriteriaQuery} from a {@link PartTree}.
@@ -52,7 +47,7 @@ public class JpaQueryCreator extends AbstractQueryCreator<CriteriaQuery<Object>,
5247 private final CriteriaBuilder builder ;
5348 private final Root <?> root ;
5449 private final CriteriaQuery <Object > query ;
55- private final ParameterExpressionProvider provider ;
50+ private final ParameterMetadataProvider provider ;
5651
5752 /**
5853 * Create a new {@link JpaQueryCreator}.
@@ -62,33 +57,29 @@ public class JpaQueryCreator extends AbstractQueryCreator<CriteriaQuery<Object>,
6257 * @param accessor
6358 * @param em
6459 */
65- public JpaQueryCreator (PartTree tree , Class <?> domainClass , Parameters parameters , EntityManager em ) {
60+ public JpaQueryCreator (PartTree tree , Class <?> domainClass , CriteriaBuilder builder ,
61+ ParameterMetadataProvider provider ) {
6662
6763 super (tree );
6864
69- this .builder = em . getCriteriaBuilder () ;
65+ this .builder = builder ;
7066 this .query = builder .createQuery ().distinct (tree .isDistinct ());
7167 this .root = query .from (domainClass );
72- this .provider = new ParameterExpressionProvider ( builder , parameters . getBindableParameters ()) ;
68+ this .provider = provider ;
7369 }
7470
7571 /**
7672 * Returns all {@link ParameterExpression} created when creating the query.
7773 *
7874 * @return the parameterExpressions
7975 */
80- public List <ParameterExpression <?>> getParameterExpressions () {
81-
76+ public List <ParameterMetadata <?>> getParameterExpressions () {
8277 return provider .getExpressions ();
8378 }
8479
8580 /*
8681 * (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)
9283 */
9384 @ Override
9485 protected Predicate create (Part part , Iterator <Object > iterator ) {
@@ -98,11 +89,7 @@ protected Predicate create(Part part, Iterator<Object> iterator) {
9889
9990 /*
10091 * (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)
10693 */
10794 @ Override
10895 protected Predicate and (Part part , Predicate base , Iterator <Object > iterator ) {
@@ -112,10 +99,7 @@ protected Predicate and(Part part, Predicate base, Iterator<Object> iterator) {
11299
113100 /*
114101 * (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)
119103 */
120104 @ Override
121105 protected Predicate or (Predicate base , Predicate predicate ) {
@@ -146,7 +130,6 @@ protected final CriteriaQuery<Object> complete(Predicate predicate, Sort sort) {
146130 */
147131 protected CriteriaQuery <Object > complete (Predicate predicate , Sort sort , CriteriaQuery <Object > query ,
148132 CriteriaBuilder builder , Root <?> root ) {
149-
150133 return this .query .select (root ).where (predicate ).orderBy (QueryUtils .toOrders (sort , root , builder ));
151134 }
152135
@@ -159,7 +142,6 @@ protected CriteriaQuery<Object> complete(Predicate predicate, Sort sort, Criteri
159142 * @return
160143 */
161144 private Predicate toPredicate (Part part , Root <?> root ) {
162-
163145 return new PredicateBuilder (part , root ).build ();
164146 }
165147
@@ -180,89 +162,6 @@ private <T> Expression<T> getTypedPath(Root<?> root, Part part, Class<T> type) {
180162 return toExpressionRecursively (root , part .getProperty ());
181163 }
182164
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-
266165 /**
267166 * Simple builder to contain logic to create JPA {@link Predicate}s from {@link Part}s.
268167 *
@@ -300,39 +199,44 @@ public Predicate build() {
300199
301200 switch (part .getType ()) {
302201 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 () );
306205 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 ());
308208 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 ());
310211 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 ( ));
312213 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 ());
314216 case IS_NULL :
315217 return path .isNull ();
316218 case IS_NOT_NULL :
317219 return path .isNotNull ();
318220 case NOT_IN :
319- return path .in (provider .next (Collection .class )).not ();
221+ return path .in (provider .next (part , Collection .class ). getExpression ( )).not ();
320222 case IN :
321- return path .in (provider .next (Collection .class ));
223+ return path .in (provider .next (part , Collection .class ). getExpression ( ));
322224 case LIKE :
323225 case NOT_LIKE :
324226 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 ( ));
326228 Predicate like = builder .like (propertyExpression , parameterExpression );
327229 return part .getType () == Type .LIKE ? like : like .not ();
328230 case TRUE :
329231 return builder .isTrue (getTypedPath (root , part , Boolean .class ));
330232 case FALSE :
331233 return builder .isFalse (getTypedPath (root , part , Boolean .class ));
332234 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 ()));
334238 case NEGATING_SIMPLE_PROPERTY :
335- return builder .notEqual (upperIfIgnoreCase (path ), upperIfIgnoreCase (provider .next ()));
239+ return builder .notEqual (upperIfIgnoreCase (path ), upperIfIgnoreCase (provider .next (part ). getExpression ( )));
336240 default :
337241 throw new IllegalArgumentException ("Unsupported keyword + " + part .getType ());
338242 }
0 commit comments