Skip to content

Commit 74ff5b3

Browse files
committed
DATAJPA-1575 - Introduce QueryMetadataCache.
1 parent 6e2032e commit 74ff5b3

File tree

10 files changed

+265
-84
lines changed

10 files changed

+265
-84
lines changed

src/main/java/org/springframework/data/jpa/repository/query/AbstractStringBasedJpaQuery.java

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,6 @@
1515
*/
1616
package org.springframework.data.jpa.repository.query;
1717

18-
import static org.springframework.data.jpa.repository.query.QueryParameterSetter.ErrorHandling.*;
19-
2018
import javax.persistence.EntityManager;
2119
import javax.persistence.Query;
2220

@@ -42,6 +40,7 @@ abstract class AbstractStringBasedJpaQuery extends AbstractJpaQuery {
4240
private final DeclaredQuery countQuery;
4341
private final QueryMethodEvaluationContextProvider evaluationContextProvider;
4442
private final SpelExpressionParser parser;
43+
private final QueryParameterSetter.QueryMetadataCache metadataCache = new QueryParameterSetter.QueryMetadataCache();
4544

4645
/**
4746
* Creates a new {@link AbstractStringBasedJpaQuery} from the given {@link JpaQueryMethod}, {@link EntityManager} and
@@ -86,9 +85,11 @@ public Query doCreateQuery(JpaParametersParameterAccessor accessor) {
8685

8786
Query query = createJpaQuery(sortedQueryString, processor.getReturnedType());
8887

88+
QueryParameterSetter.QueryMetadata metadata = metadataCache.getMetadata(sortedQueryString, query);
89+
8990
// it is ok to reuse the binding contained in the ParameterBinder although we create a new query String because the
9091
// parameters in the query do not change.
91-
return parameterBinder.get().bindAndPrepare(query, accessor);
92+
return parameterBinder.get().bindAndPrepare(query, metadata, accessor);
9293
}
9394

9495
/*
@@ -116,7 +117,11 @@ protected Query doCreateCountQuery(JpaParametersParameterAccessor accessor) {
116117
? em.createNativeQuery(queryString) //
117118
: em.createQuery(queryString, Long.class);
118119

119-
return parameterBinder.get().bind(query, accessor, LENIENT);
120+
QueryParameterSetter.QueryMetadata metadata = metadataCache.getMetadata(queryString, query);
121+
122+
parameterBinder.get().bind(metadata.withQuery(query), accessor, QueryParameterSetter.ErrorHandling.LENIENT);
123+
124+
return query;
120125
}
121126

122127
/**

src/main/java/org/springframework/data/jpa/repository/query/JpaQueryExecution.java

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -176,7 +176,6 @@ protected Object doExecute(final AbstractJpaQuery repositoryQuery, JpaParameters
176176

177177
return PageableExecutionUtils.getPage(query.getResultList(), accessor.getPageable(),
178178
() -> count(repositoryQuery, accessor));
179-
180179
}
181180

182181
private long count(AbstractJpaQuery repositoryQuery, JpaParametersParameterAccessor accessor) {

src/main/java/org/springframework/data/jpa/repository/query/NamedQuery.java

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ final class NamedQuery extends AbstractJpaQuery {
5555
private final QueryExtractor extractor;
5656
private final boolean namedCountQueryIsPresent;
5757
private final DeclaredQuery declaredQuery;
58+
private final QueryParameterSetter.QueryMetadataCache metadataCache;
5859

5960
/**
6061
* Creates a new {@link NamedQuery}.
@@ -93,6 +94,8 @@ private NamedQuery(JpaQueryMethod method, EntityManager em) {
9394
LOG.warn("Finder method {} is backed by a NamedQuery" + " but contains a Pageable parameter! Sorting delivered "
9495
+ "via this Pageable will not be applied!", method);
9596
}
97+
98+
this.metadataCache = new QueryParameterSetter.QueryMetadataCache();
9699
}
97100

98101
/**
@@ -166,7 +169,9 @@ protected Query doCreateQuery(JpaParametersParameterAccessor accessor) {
166169
? em.createNamedQuery(queryName) //
167170
: em.createNamedQuery(queryName, typeToRead);
168171

169-
return parameterBinder.get().bindAndPrepare(query, accessor);
172+
QueryParameterSetter.QueryMetadata metadata = metadataCache.getMetadata(queryName, query);
173+
174+
return parameterBinder.get().bindAndPrepare(query, metadata, accessor);
170175
}
171176

172177
/*
@@ -179,18 +184,21 @@ protected TypedQuery<Long> doCreateCountQuery(JpaParametersParameterAccessor acc
179184
EntityManager em = getEntityManager();
180185
TypedQuery<Long> countQuery;
181186

187+
String cacheKey;
182188
if (namedCountQueryIsPresent) {
183-
189+
cacheKey = countQueryName;
184190
countQuery = em.createNamedQuery(countQueryName, Long.class);
185191

186192
} else {
187193

188194
String countQueryString = declaredQuery.deriveCountQuery(null, countProjection).getQueryString();
189-
195+
cacheKey = countQueryString;
190196
countQuery = em.createQuery(countQueryString, Long.class);
191197
}
192198

193-
return parameterBinder.get().bind(countQuery, accessor, LENIENT);
199+
QueryParameterSetter.QueryMetadata metadata = metadataCache.getMetadata(cacheKey, countQuery);
200+
201+
return parameterBinder.get().bind(countQuery, metadata, accessor);
194202
}
195203

196204
/*

src/main/java/org/springframework/data/jpa/repository/query/ParameterBinder.java

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -69,17 +69,18 @@ public ParameterBinder(JpaParameters parameters, Iterable<QueryParameterSetter>
6969
this.useJpaForPaging = useJpaForPaging;
7070
}
7171

72-
public <T extends Query> T bind(T jpaQuery, JpaParametersParameterAccessor accessor) {
73-
return bind(jpaQuery, accessor, ErrorHandling.STRICT);
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;
7476
}
7577

76-
public <T extends Query> T bind(T jpaQuery, JpaParametersParameterAccessor accessor, ErrorHandling errorHandling) {
78+
public void bind(QueryParameterSetter.BindableQuery query, JpaParametersParameterAccessor accessor,
79+
ErrorHandling errorHandling) {
7780

7881
for (QueryParameterSetter setter : parameterSetters) {
79-
setter.setParameter(jpaQuery, accessor, errorHandling);
82+
setter.setParameter(query, accessor, errorHandling);
8083
}
81-
82-
return jpaQuery;
8384
}
8485

8586
/**
@@ -88,19 +89,18 @@ public <T extends Query> T bind(T jpaQuery, JpaParametersParameterAccessor acces
8889
* @param query must not be {@literal null}.
8990
* @param values values of method parameters to be assigned to the query parameters.
9091
*/
91-
Query bindAndPrepare(Query query, JpaParametersParameterAccessor accessor) {
92-
93-
Assert.notNull(query, "Query must not be null!");
92+
Query bindAndPrepare(Query query, QueryParameterSetter.QueryMetadata metadata,
93+
JpaParametersParameterAccessor accessor) {
9494

95-
Query result = bind(query, accessor);
95+
bind(query, metadata, accessor);
9696

9797
if (!useJpaForPaging || !parameters.hasPageableParameter() || accessor.getPageable().isUnpaged()) {
98-
return result;
98+
return query;
9999
}
100100

101-
result.setFirstResult((int) accessor.getPageable().getOffset());
102-
result.setMaxResults(accessor.getPageable().getPageSize());
101+
query.setFirstResult((int) accessor.getPageable().getOffset());
102+
query.setMaxResults(accessor.getPageable().getPageSize());
103103

104-
return result;
104+
return query;
105105
}
106106
}

src/main/java/org/springframework/data/jpa/repository/query/PartTreeJpaQuery.java

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -214,6 +214,7 @@ private class QueryPreparer {
214214
private final @Nullable List<ParameterMetadata<?>> expressions;
215215
private final PersistenceProvider persistenceProvider;
216216
private final Map<List<ParameterMetadata<?>>, ParameterBinder> binderCache = new ConcurrentHashMap<>();
217+
private final QueryParameterSetter.QueryMetadataCache metadataCache = new QueryParameterSetter.QueryMetadataCache();
217218

218219
QueryPreparer(PersistenceProvider persistenceProvider, boolean recreateQueries) {
219220

@@ -251,7 +252,9 @@ public Query createQuery(JpaParametersParameterAccessor accessor) {
251252
throw new IllegalStateException("ParameterBinder is null!");
252253
}
253254

254-
return restrictMaxResultsIfNecessary(invokeBinding(parameterBinder, createQuery(criteriaQuery), accessor));
255+
TypedQuery<?> query = createQuery(criteriaQuery);
256+
257+
return restrictMaxResultsIfNecessary(invokeBinding(parameterBinder, query, accessor, this.metadataCache));
255258
}
256259

257260
/**
@@ -327,10 +330,12 @@ protected JpaQueryCreator createCreator(PersistenceProvider persistenceProvider,
327330
/**
328331
* Invokes parameter binding on the given {@link TypedQuery}.
329332
*/
330-
protected Query invokeBinding(ParameterBinder binder, TypedQuery<?> query,
331-
JpaParametersParameterAccessor accessor) {
333+
protected Query invokeBinding(ParameterBinder binder, TypedQuery<?> query, JpaParametersParameterAccessor accessor,
334+
QueryParameterSetter.QueryMetadataCache metadataCache) {
335+
336+
QueryParameterSetter.QueryMetadata metadata = metadataCache.getMetadata("query", query);
332337

333-
return binder.bindAndPrepare(query, accessor);
338+
return binder.bindAndPrepare(query, metadata, accessor);
334339
}
335340

336341
private ParameterBinder getBinder(List<ParameterMetadata<?>> expressions) {
@@ -382,9 +387,12 @@ protected JpaQueryCreator createCreator(PersistenceProvider persistenceProvider,
382387
* @see QueryPreparer#invokeBinding(ParameterBinder, TypedQuery, JpaParametersParameterAccessor)
383388
*/
384389
@Override
385-
protected Query invokeBinding(ParameterBinder binder, TypedQuery<?> query,
386-
JpaParametersParameterAccessor accessor) {
387-
return binder.bind(query, accessor);
390+
protected Query invokeBinding(ParameterBinder binder, TypedQuery<?> query, JpaParametersParameterAccessor accessor,
391+
QueryParameterSetter.QueryMetadataCache metadataCache) {
392+
393+
QueryParameterSetter.QueryMetadata metadata = metadataCache.getMetadata("countquery", query);
394+
395+
return binder.bind(query, metadata, accessor);
388396
}
389397
}
390398
}

0 commit comments

Comments
 (0)