1 /*
2 * Copyright 2008-2020 the original author or authors.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * https://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16 package org.springframework.data.jpa.repository.query;
17
18 import javax.persistence.Query;
19
20 import org.springframework.data.jpa.repository.query.QueryParameterSetter.ErrorHandling;
21 import org.springframework.util.Assert;
22
23 /**
24 * {@link ParameterBinder} is used to bind method parameters to a {@link Query}. This is usually done whenever an
25 * {@link AbstractJpaQuery} is executed.
26 *
27 * @author Oliver Gierke
28 * @author Thomas Darimont
29 * @author Mark Paluch
30 * @author Christoph Strobl
31 * @author Jens Schauder
32 */
33 public class ParameterBinder {
34
35 static final String PARAMETER_NEEDS_TO_BE_NAMED = "For queries with named parameters you need to use provide names for method parameters. Use @Param for query method parameters, or when on Java 8+ use the javac flag -parameters.";
36
37 private final JpaParameters parameters;
38 private final Iterable<QueryParameterSetter> parameterSetters;
39 private final boolean useJpaForPaging;
40
41 /**
42 * Creates a new {@link ParameterBinder} for the given {@link JpaParameters} and {@link QueryParameterSetter}s.
43 * Defaults to use JPA API to apply pagination offsets.
44 *
45 * @param parameters must not be {@literal null}.
46 * @param parameterSetters must not be {@literal null}.
47 * @since 2.0.6
48 */
49 ParameterBinder(JpaParameters parameters, Iterable<QueryParameterSetter> parameterSetters) {
50 this(parameters, parameterSetters, true);
51 }
52
53 /**
54 * Creates a new {@link ParameterBinder} for the given {@link JpaParameters} and {@link QueryParameterSetter}s.
55 *
56 * @param parameters must not be {@literal null}.
57 * @param parameterSetters must not be {@literal null}.
58 * @param useJpaForPaging determines whether {@link Query#setFirstResult(int)} and {@link Query#setMaxResults(int)}
59 * shall be used for paging.
60 */
61 public ParameterBinder(JpaParameters parameters, Iterable<QueryParameterSetter> parameterSetters,
62 boolean useJpaForPaging) {
63
64 Assert.notNull(parameters, "JpaParameters must not be null!");
65 Assert.notNull(parameterSetters, "Parameter setters must not be null!");
66
67 this.parameters = parameters;
68 this.parameterSetters = parameterSetters;
69 this.useJpaForPaging = useJpaForPaging;
70 }
71
72 public <T extends Query> T bind(T jpaQuery, QueryParameterSetter.QueryMetadata metadata,
73 JpaParametersParameterAccessor accessor) {
74 bind(metadata.withQuery(jpaQuery), accessor, ErrorHandling.STRICT);
75 return jpaQuery;
76 }
77
78 public void bind(QueryParameterSetter.BindableQuery query, JpaParametersParameterAccessor accessor,
79 ErrorHandling errorHandling) {
80
81 for (QueryParameterSetter setter : parameterSetters) {
82 setter.setParameter(query, accessor, errorHandling);
83 }
84 }
85
86 /**
87 * Binds the parameters to the given query and applies special parameter types (e.g. pagination).
88 *
89 * @param query must not be {@literal null}.
90 * @param values values of method parameters to be assigned to the query parameters.
91 */
92 Query bindAndPrepare(Query query, QueryParameterSetter.QueryMetadata metadata,
93 JpaParametersParameterAccessor accessor) {
94
95 bind(query, metadata, accessor);
96
97 if (!useJpaForPaging || !parameters.hasPageableParameter() || accessor.getPageable().isUnpaged()) {
98 return query;
99 }
100
101 query.setFirstResult((int) accessor.getPageable().getOffset());
102 query.setMaxResults(accessor.getPageable().getPageSize());
103
104 return query;
105 }
106 }
107