DATAJPA-804 - Support for projections on query methods.
Based on the work for DATACMNS-89 we now use the metadata exposed by ResourceProcessor to optimize queries that are to be projected on the query execution level. If a projection interface is used that's not using any dynamic expression, we now explicitly query for a JPA Tuple consisting of all properties required for the projection interface. The same applies to DTOs that use an @PersistenceConstructor. Related tickets: DATACMNS-89.
This commit is contained in:
@@ -15,14 +15,18 @@
|
||||
*/
|
||||
package org.springframework.data.jpa.repository.query;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.persistence.EntityManager;
|
||||
import javax.persistence.LockModeType;
|
||||
import javax.persistence.Query;
|
||||
import javax.persistence.QueryHint;
|
||||
import javax.persistence.Tuple;
|
||||
import javax.persistence.TupleElement;
|
||||
import javax.persistence.TypedQuery;
|
||||
|
||||
import org.springframework.core.convert.converter.Converter;
|
||||
import org.springframework.data.jpa.repository.EntityGraph;
|
||||
import org.springframework.data.jpa.repository.query.JpaQueryExecution.CollectionExecution;
|
||||
import org.springframework.data.jpa.repository.query.JpaQueryExecution.ModifyingExecution;
|
||||
@@ -31,7 +35,9 @@ import org.springframework.data.jpa.repository.query.JpaQueryExecution.Procedure
|
||||
import org.springframework.data.jpa.repository.query.JpaQueryExecution.SingleEntityExecution;
|
||||
import org.springframework.data.jpa.repository.query.JpaQueryExecution.SlicedExecution;
|
||||
import org.springframework.data.jpa.repository.query.JpaQueryExecution.StreamExecution;
|
||||
import org.springframework.data.repository.query.ParametersParameterAccessor;
|
||||
import org.springframework.data.repository.query.RepositoryQuery;
|
||||
import org.springframework.data.repository.query.ResultProcessor;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
@@ -49,6 +55,7 @@ public abstract class AbstractJpaQuery implements RepositoryQuery {
|
||||
* Creates a new {@link AbstractJpaQuery} from the given {@link JpaQueryMethod}.
|
||||
*
|
||||
* @param method
|
||||
* @param resultFactory
|
||||
* @param em
|
||||
*/
|
||||
public AbstractJpaQuery(JpaQueryMethod method, EntityManager em) {
|
||||
@@ -62,30 +69,24 @@ public abstract class AbstractJpaQuery implements RepositoryQuery {
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see
|
||||
* org.springframework.data.repository.query.RepositoryQuery#getQueryMethod
|
||||
* ()
|
||||
* @see org.springframework.data.repository.query.RepositoryQuery#getQueryMethod()
|
||||
*/
|
||||
public JpaQueryMethod getQueryMethod() {
|
||||
|
||||
return method;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the em
|
||||
* Returns the {@link EntityManager}.
|
||||
*
|
||||
* @return will never be {@literal null}.
|
||||
*/
|
||||
protected EntityManager getEntityManager() {
|
||||
|
||||
return em;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see
|
||||
* org.springframework.data.repository.query.RepositoryQuery#execute(java
|
||||
* .lang.Object[])
|
||||
* @see org.springframework.data.repository.query.RepositoryQuery#execute(java.lang.Object[])
|
||||
*/
|
||||
public Object execute(Object[] parameters) {
|
||||
return doExecute(getExecution(), parameters);
|
||||
@@ -97,7 +98,13 @@ public abstract class AbstractJpaQuery implements RepositoryQuery {
|
||||
* @return
|
||||
*/
|
||||
private Object doExecute(JpaQueryExecution execution, Object[] values) {
|
||||
return execution.execute(this, values);
|
||||
|
||||
Object result = execution.execute(this, values);
|
||||
|
||||
ParametersParameterAccessor accessor = new ParametersParameterAccessor(method.getParameters(), values);
|
||||
ResultProcessor withDynamicProjection = method.getResultProcessor().withDynamicProjection(accessor);
|
||||
|
||||
return withDynamicProjection.processResult(result, TupleConverter.INSTANCE);
|
||||
}
|
||||
|
||||
protected JpaQueryExecution getExecution() {
|
||||
@@ -212,4 +219,47 @@ public abstract class AbstractJpaQuery implements RepositoryQuery {
|
||||
* @return
|
||||
*/
|
||||
protected abstract Query doCreateCountQuery(Object[] values);
|
||||
|
||||
private static enum TupleConverter implements Converter<Object, Object> {
|
||||
|
||||
INSTANCE;
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.core.convert.converter.Converter#convert(java.lang.Object)
|
||||
*/
|
||||
@Override
|
||||
public Object convert(Object source) {
|
||||
|
||||
if (!(source instanceof Tuple)) {
|
||||
return source;
|
||||
}
|
||||
|
||||
Tuple tuple = (Tuple) source;
|
||||
Map<String, Object> result = new HashMap<String, Object>();
|
||||
|
||||
for (TupleElement<?> element : tuple.getElements()) {
|
||||
|
||||
String alias = element.getAlias();
|
||||
|
||||
if (alias == null || isIndexAsString(alias)) {
|
||||
throw new IllegalStateException("No aliases found in result tuple! Make sure your query defines aliases!");
|
||||
}
|
||||
|
||||
result.put(element.getAlias(), tuple.get(element));
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private static boolean isIndexAsString(String source) {
|
||||
|
||||
try {
|
||||
Integer.parseInt(source);
|
||||
return true;
|
||||
} catch (NumberFormatException o_O) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,10 +17,13 @@ package org.springframework.data.jpa.repository.query;
|
||||
|
||||
import javax.persistence.EntityManager;
|
||||
import javax.persistence.Query;
|
||||
import javax.persistence.Tuple;
|
||||
|
||||
import org.springframework.data.repository.query.EvaluationContextProvider;
|
||||
import org.springframework.data.repository.query.ParameterAccessor;
|
||||
import org.springframework.data.repository.query.ParametersParameterAccessor;
|
||||
import org.springframework.data.repository.query.ResultProcessor;
|
||||
import org.springframework.data.repository.query.ReturnedType;
|
||||
import org.springframework.expression.spel.standard.SpelExpressionParser;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
@@ -96,7 +99,12 @@ abstract class AbstractStringBasedJpaQuery extends AbstractJpaQuery {
|
||||
* @return
|
||||
*/
|
||||
public Query createJpaQuery(String queryString) {
|
||||
return getEntityManager().createQuery(queryString);
|
||||
|
||||
ResultProcessor resultFactory = getQueryMethod().getResultProcessor();
|
||||
ReturnedType returnedType = resultFactory.getReturnedType();
|
||||
EntityManager em = getEntityManager();
|
||||
|
||||
return returnedType.isProjecting() ? em.createQuery(queryString, Tuple.class) : em.createQuery(queryString);
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -17,10 +17,12 @@ package org.springframework.data.jpa.repository.query;
|
||||
|
||||
import javax.persistence.criteria.CriteriaBuilder;
|
||||
import javax.persistence.criteria.CriteriaQuery;
|
||||
import javax.persistence.criteria.Expression;
|
||||
import javax.persistence.criteria.Predicate;
|
||||
import javax.persistence.criteria.Root;
|
||||
|
||||
import org.springframework.data.domain.Sort;
|
||||
import org.springframework.data.repository.query.ReturnedType;
|
||||
import org.springframework.data.repository.query.parser.PartTree;
|
||||
|
||||
/**
|
||||
@@ -38,9 +40,9 @@ public class JpaCountQueryCreator extends JpaQueryCreator {
|
||||
* @param parameters
|
||||
* @param em
|
||||
*/
|
||||
public JpaCountQueryCreator(PartTree tree, Class<?> domainClass, CriteriaBuilder builder,
|
||||
public JpaCountQueryCreator(PartTree tree, ReturnedType type, CriteriaBuilder builder,
|
||||
ParameterMetadataProvider provider) {
|
||||
super(tree, domainClass, builder, provider);
|
||||
super(tree, type, builder, provider);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -48,10 +50,10 @@ public class JpaCountQueryCreator extends JpaQueryCreator {
|
||||
* @see org.springframework.data.jpa.repository.query.JpaQueryCreator#complete(javax.persistence.criteria.Predicate, org.springframework.data.domain.Sort, javax.persistence.criteria.CriteriaQuery, javax.persistence.criteria.CriteriaBuilder, javax.persistence.criteria.Root)
|
||||
*/
|
||||
@Override
|
||||
protected CriteriaQuery<Object> complete(Predicate predicate, Sort sort, CriteriaQuery<Object> query,
|
||||
CriteriaBuilder builder, Root<?> root) {
|
||||
protected CriteriaQuery<? extends Object> complete(Predicate predicate, Sort sort,
|
||||
CriteriaQuery<? extends Object> query, CriteriaBuilder builder, Root<?> root) {
|
||||
|
||||
CriteriaQuery<Object> select = query.select(builder.count(root));
|
||||
CriteriaQuery<? extends Object> select = query.select((Expression) builder.count(root));
|
||||
return predicate == null ? select : select.where(predicate);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,6 +18,7 @@ package org.springframework.data.jpa.repository.query;
|
||||
import static org.springframework.data.jpa.repository.query.QueryUtils.*;
|
||||
import static org.springframework.data.repository.query.parser.Part.Type.*;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
@@ -28,10 +29,12 @@ import javax.persistence.criteria.Expression;
|
||||
import javax.persistence.criteria.Path;
|
||||
import javax.persistence.criteria.Predicate;
|
||||
import javax.persistence.criteria.Root;
|
||||
import javax.persistence.criteria.Selection;
|
||||
|
||||
import org.springframework.data.domain.Sort;
|
||||
import org.springframework.data.jpa.repository.query.ParameterMetadataProvider.ParameterMetadata;
|
||||
import org.springframework.data.mapping.PropertyPath;
|
||||
import org.springframework.data.repository.query.ReturnedType;
|
||||
import org.springframework.data.repository.query.parser.AbstractQueryCreator;
|
||||
import org.springframework.data.repository.query.parser.Part;
|
||||
import org.springframework.data.repository.query.parser.Part.Type;
|
||||
@@ -43,12 +46,13 @@ import org.springframework.util.Assert;
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
public class JpaQueryCreator extends AbstractQueryCreator<CriteriaQuery<Object>, Predicate> {
|
||||
public class JpaQueryCreator extends AbstractQueryCreator<CriteriaQuery<? extends Object>, Predicate> {
|
||||
|
||||
private final CriteriaBuilder builder;
|
||||
private final Root<?> root;
|
||||
private final CriteriaQuery<Object> query;
|
||||
private final CriteriaQuery<? extends Object> query;
|
||||
private final ParameterMetadataProvider provider;
|
||||
private final ReturnedType returnedType;
|
||||
|
||||
/**
|
||||
* Create a new {@link JpaQueryCreator}.
|
||||
@@ -58,15 +62,21 @@ public class JpaQueryCreator extends AbstractQueryCreator<CriteriaQuery<Object>,
|
||||
* @param accessor
|
||||
* @param em
|
||||
*/
|
||||
public JpaQueryCreator(PartTree tree, Class<?> domainClass, CriteriaBuilder builder,
|
||||
public JpaQueryCreator(PartTree tree, ReturnedType type, CriteriaBuilder builder,
|
||||
ParameterMetadataProvider provider) {
|
||||
|
||||
super(tree);
|
||||
|
||||
Class<?> typeToRead = type.getTypeToRead();
|
||||
|
||||
CriteriaQuery<? extends Object> criteriaQuery = typeToRead == null ? builder.createTupleQuery()
|
||||
: builder.createQuery(typeToRead);
|
||||
|
||||
this.builder = builder;
|
||||
this.query = builder.createQuery().distinct(tree.isDistinct());
|
||||
this.root = query.from(domainClass);
|
||||
this.query = criteriaQuery.distinct(tree.isDistinct());
|
||||
this.root = query.from(type.getDomainType());
|
||||
this.provider = provider;
|
||||
this.returnedType = type;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -94,7 +104,6 @@ public class JpaQueryCreator extends AbstractQueryCreator<CriteriaQuery<Object>,
|
||||
*/
|
||||
@Override
|
||||
protected Predicate and(Part part, Predicate base, Iterator<Object> iterator) {
|
||||
|
||||
return builder.and(base, toPredicate(part, root));
|
||||
}
|
||||
|
||||
@@ -104,7 +113,6 @@ public class JpaQueryCreator extends AbstractQueryCreator<CriteriaQuery<Object>,
|
||||
*/
|
||||
@Override
|
||||
protected Predicate or(Predicate base, Predicate predicate) {
|
||||
|
||||
return builder.or(base, predicate);
|
||||
}
|
||||
|
||||
@@ -114,8 +122,7 @@ public class JpaQueryCreator extends AbstractQueryCreator<CriteriaQuery<Object>,
|
||||
* and {@link CriteriaBuilder}.
|
||||
*/
|
||||
@Override
|
||||
protected final CriteriaQuery<Object> complete(Predicate predicate, Sort sort) {
|
||||
|
||||
protected final CriteriaQuery<? extends Object> complete(Predicate predicate, Sort sort) {
|
||||
return complete(predicate, sort, query, builder, root);
|
||||
}
|
||||
|
||||
@@ -129,10 +136,24 @@ public class JpaQueryCreator extends AbstractQueryCreator<CriteriaQuery<Object>,
|
||||
* @param builder
|
||||
* @return
|
||||
*/
|
||||
protected CriteriaQuery<Object> complete(Predicate predicate, Sort sort, CriteriaQuery<Object> query,
|
||||
CriteriaBuilder builder, Root<?> root) {
|
||||
@SuppressWarnings({ "unchecked", "rawtypes" })
|
||||
protected CriteriaQuery<? extends Object> complete(Predicate predicate, Sort sort,
|
||||
CriteriaQuery<? extends Object> query, CriteriaBuilder builder, Root<?> root) {
|
||||
|
||||
CriteriaQuery<Object> select = this.query.select(root).orderBy(QueryUtils.toOrders(sort, root, builder));
|
||||
if (returnedType.needsCustomConstruction()) {
|
||||
|
||||
List<Selection<?>> selections = new ArrayList<Selection<?>>();
|
||||
|
||||
for (String property : returnedType.getInputProperties()) {
|
||||
selections.add(root.get(property).alias(property));
|
||||
}
|
||||
|
||||
query = query.multiselect(selections);
|
||||
} else {
|
||||
query = query.select((Root) root);
|
||||
}
|
||||
|
||||
CriteriaQuery<? extends Object> select = query.orderBy(QueryUtils.toOrders(sort, root, builder));
|
||||
return predicate == null ? select : select.where(predicate);
|
||||
}
|
||||
|
||||
@@ -148,6 +169,23 @@ public class JpaQueryCreator extends AbstractQueryCreator<CriteriaQuery<Object>,
|
||||
return new PredicateBuilder(part, root).build();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a path to a {@link Comparable}.
|
||||
*
|
||||
* @param root
|
||||
* @param part
|
||||
* @return
|
||||
*/
|
||||
@SuppressWarnings({ "rawtypes" })
|
||||
private Expression<? extends Comparable> getComparablePath(Root<?> root, Part part) {
|
||||
|
||||
return getTypedPath(root, part);
|
||||
}
|
||||
|
||||
private <T> Expression<T> getTypedPath(Root<?> root, Part part) {
|
||||
return toExpressionRecursively(root, part.getProperty());
|
||||
}
|
||||
|
||||
/**
|
||||
* Simple builder to contain logic to create JPA {@link Predicate}s from {@link Part}s.
|
||||
*
|
||||
|
||||
@@ -41,16 +41,16 @@ enum JpaQueryFactory {
|
||||
* Creates a {@link RepositoryQuery} from the given {@link QueryMethod} that is potentially annotated with
|
||||
* {@link Query}.
|
||||
*
|
||||
* @param queryMethod must not be {@literal null}.
|
||||
* @param method must not be {@literal null}.
|
||||
* @param em must not be {@literal null}.
|
||||
* @param evaluationContextProvider
|
||||
* @return the {@link RepositoryQuery} derived from the annotation or {@code null} if no annotation found.
|
||||
*/
|
||||
AbstractJpaQuery fromQueryAnnotation(JpaQueryMethod queryMethod, EntityManager em,
|
||||
AbstractJpaQuery fromQueryAnnotation(JpaQueryMethod method, EntityManager em,
|
||||
EvaluationContextProvider evaluationContextProvider) {
|
||||
|
||||
LOG.debug("Looking up query for method {}", queryMethod.getName());
|
||||
return fromMethodWithQueryString(queryMethod, em, queryMethod.getAnnotatedQuery(), evaluationContextProvider);
|
||||
LOG.debug("Looking up query for method {}", method.getName());
|
||||
return fromMethodWithQueryString(method, em, method.getAnnotatedQuery(), evaluationContextProvider);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -69,8 +69,8 @@ enum JpaQueryFactory {
|
||||
return null;
|
||||
}
|
||||
|
||||
return method.isNativeQuery() ? new NativeJpaQuery(method, em, queryString, evaluationContextProvider, PARSER) : //
|
||||
new SimpleJpaQuery(method, em, queryString, evaluationContextProvider, PARSER);
|
||||
return method.isNativeQuery() ? new NativeJpaQuery(method, em, queryString, evaluationContextProvider, PARSER)
|
||||
: new SimpleJpaQuery(method, em, queryString, evaluationContextProvider, PARSER);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -20,6 +20,7 @@ import java.lang.reflect.Method;
|
||||
import javax.persistence.EntityManager;
|
||||
|
||||
import org.springframework.data.jpa.provider.QueryExtractor;
|
||||
import org.springframework.data.projection.ProjectionFactory;
|
||||
import org.springframework.data.repository.core.NamedQueries;
|
||||
import org.springframework.data.repository.core.RepositoryMetadata;
|
||||
import org.springframework.data.repository.query.EvaluationContextProvider;
|
||||
@@ -65,12 +66,14 @@ public final class JpaQueryLookupStrategy {
|
||||
this.provider = extractor;
|
||||
}
|
||||
|
||||
/*
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.repository.query.QueryLookupStrategy#resolveQuery(java.lang.reflect.Method, org.springframework.data.repository.core.RepositoryMetadata, org.springframework.data.repository.core.NamedQueries)
|
||||
* @see org.springframework.data.repository.query.QueryLookupStrategy#resolveQuery(java.lang.reflect.Method, org.springframework.data.repository.core.RepositoryMetadata, org.springframework.data.projection.ProjectionFactory, org.springframework.data.repository.core.NamedQueries)
|
||||
*/
|
||||
public final RepositoryQuery resolveQuery(Method method, RepositoryMetadata metadata, NamedQueries namedQueries) {
|
||||
return resolveQuery(new JpaQueryMethod(method, metadata, provider), em, namedQueries);
|
||||
@Override
|
||||
public final RepositoryQuery resolveQuery(Method method, RepositoryMetadata metadata, ProjectionFactory factory,
|
||||
NamedQueries namedQueries) {
|
||||
return resolveQuery(new JpaQueryMethod(method, metadata, factory, provider), em, namedQueries);
|
||||
}
|
||||
|
||||
protected abstract RepositoryQuery resolveQuery(JpaQueryMethod method, EntityManager em, NamedQueries namedQueries);
|
||||
@@ -94,8 +97,8 @@ public final class JpaQueryLookupStrategy {
|
||||
try {
|
||||
return new PartTreeJpaQuery(method, em);
|
||||
} catch (IllegalArgumentException e) {
|
||||
throw new IllegalArgumentException(String.format("Could not create query metamodel for method %s!",
|
||||
method.toString()), e);
|
||||
throw new IllegalArgumentException(
|
||||
String.format("Could not create query metamodel for method %s!", method.toString()), e);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -157,8 +160,8 @@ public final class JpaQueryLookupStrategy {
|
||||
return query;
|
||||
}
|
||||
|
||||
throw new IllegalStateException(String.format(
|
||||
"Did neither find a NamedQuery nor an annotated query for method %s!", method));
|
||||
throw new IllegalStateException(
|
||||
String.format("Did neither find a NamedQuery nor an annotated query for method %s!", method));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -35,6 +35,7 @@ import org.springframework.data.jpa.repository.Lock;
|
||||
import org.springframework.data.jpa.repository.Modifying;
|
||||
import org.springframework.data.jpa.repository.Query;
|
||||
import org.springframework.data.jpa.repository.QueryHints;
|
||||
import org.springframework.data.projection.ProjectionFactory;
|
||||
import org.springframework.data.repository.core.RepositoryMetadata;
|
||||
import org.springframework.data.repository.query.Parameter;
|
||||
import org.springframework.data.repository.query.Parameters;
|
||||
@@ -77,9 +78,10 @@ public class JpaQueryMethod extends QueryMethod {
|
||||
* @param extractor must not be {@literal null}
|
||||
* @param metadata must not be {@literal null}
|
||||
*/
|
||||
public JpaQueryMethod(Method method, RepositoryMetadata metadata, QueryExtractor extractor) {
|
||||
public JpaQueryMethod(Method method, RepositoryMetadata metadata, ProjectionFactory factory,
|
||||
QueryExtractor extractor) {
|
||||
|
||||
super(method, metadata);
|
||||
super(method, metadata, factory);
|
||||
|
||||
Assert.notNull(method, "Method must not be null!");
|
||||
Assert.notNull(extractor, "Query extractor must not be null!");
|
||||
@@ -108,9 +110,9 @@ public class JpaQueryMethod extends QueryMethod {
|
||||
|
||||
if (!annotatedQuery.contains(String.format(":%s", parameter.getName()))
|
||||
&& !annotatedQuery.contains(String.format("#%s", parameter.getName()))) {
|
||||
throw new IllegalStateException(String.format(
|
||||
"Using named parameters for method %s but parameter '%s' not found in annotated query '%s'!", method,
|
||||
parameter.getName(), annotatedQuery));
|
||||
throw new IllegalStateException(
|
||||
String.format("Using named parameters for method %s but parameter '%s' not found in annotated query '%s'!",
|
||||
method, parameter.getName(), annotatedQuery));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -298,8 +300,8 @@ public class JpaQueryMethod extends QueryMethod {
|
||||
private <T> T getAnnotationValue(String attribute, Class<T> type) {
|
||||
|
||||
Query annotation = method.getAnnotation(Query.class);
|
||||
Object value = annotation == null ? AnnotationUtils.getDefaultValue(Query.class, attribute) : AnnotationUtils
|
||||
.getValue(annotation, attribute);
|
||||
Object value = annotation == null ? AnnotationUtils.getDefaultValue(Query.class, attribute)
|
||||
: AnnotationUtils.getValue(annotation, attribute);
|
||||
|
||||
return type.cast(value);
|
||||
}
|
||||
|
||||
@@ -28,6 +28,7 @@ import org.springframework.data.jpa.provider.PersistenceProvider;
|
||||
import org.springframework.data.jpa.repository.query.JpaQueryExecution.DeleteExecution;
|
||||
import org.springframework.data.jpa.repository.query.ParameterMetadataProvider.ParameterMetadata;
|
||||
import org.springframework.data.repository.query.ParametersParameterAccessor;
|
||||
import org.springframework.data.repository.query.ResultProcessor;
|
||||
import org.springframework.data.repository.query.parser.PartTree;
|
||||
|
||||
/**
|
||||
@@ -50,19 +51,21 @@ public class PartTreeJpaQuery extends AbstractJpaQuery {
|
||||
* Creates a new {@link PartTreeJpaQuery}.
|
||||
*
|
||||
* @param method must not be {@literal null}.
|
||||
* @param factory must not be {@literal null}.
|
||||
* @param em must not be {@literal null}.
|
||||
*/
|
||||
public PartTreeJpaQuery(JpaQueryMethod method, EntityManager em) {
|
||||
|
||||
super(method, em);
|
||||
this.em = em;
|
||||
|
||||
this.domainClass = method.getEntityInformation().getJavaType();
|
||||
this.tree = new PartTree(method.getName(), domainClass);
|
||||
this.parameters = method.getParameters();
|
||||
|
||||
this.countQuery = new CountQueryPreparer(parameters.potentiallySortsDynamically());
|
||||
this.query = tree.isCountProjection() ? countQuery : new QueryPreparer(parameters.potentiallySortsDynamically());
|
||||
boolean recreationRequired = parameters.hasDynamicProjection() || parameters.potentiallySortsDynamically();
|
||||
|
||||
this.countQuery = new CountQueryPreparer(recreationRequired);
|
||||
this.query = tree.isCountProjection() ? countQuery : new QueryPreparer(recreationRequired);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -189,10 +192,13 @@ public class PartTreeJpaQuery extends AbstractJpaQuery {
|
||||
CriteriaBuilder builder = entityManager.getCriteriaBuilder();
|
||||
PersistenceProvider persistenceProvider = PersistenceProvider.fromEntityManager(entityManager);
|
||||
|
||||
ParameterMetadataProvider provider = accessor == null ? new ParameterMetadataProvider(builder, parameters,
|
||||
persistenceProvider) : new ParameterMetadataProvider(builder, accessor, persistenceProvider);
|
||||
ParameterMetadataProvider provider = accessor == null
|
||||
? new ParameterMetadataProvider(builder, parameters, persistenceProvider)
|
||||
: new ParameterMetadataProvider(builder, accessor, persistenceProvider);
|
||||
|
||||
return new JpaQueryCreator(tree, domainClass, builder, provider);
|
||||
ResultProcessor resultFactory = getQueryMethod().getResultProcessor().withDynamicProjection(accessor);
|
||||
|
||||
return new JpaQueryCreator(tree, resultFactory.getReturnedType(), builder, provider);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -241,10 +247,11 @@ public class PartTreeJpaQuery extends AbstractJpaQuery {
|
||||
CriteriaBuilder builder = entityManager.getCriteriaBuilder();
|
||||
PersistenceProvider persistenceProvider = PersistenceProvider.fromEntityManager(entityManager);
|
||||
|
||||
ParameterMetadataProvider provider = accessor == null ? new ParameterMetadataProvider(builder, parameters,
|
||||
persistenceProvider) : new ParameterMetadataProvider(builder, accessor, persistenceProvider);
|
||||
ParameterMetadataProvider provider = accessor == null
|
||||
? new ParameterMetadataProvider(builder, parameters, persistenceProvider)
|
||||
: new ParameterMetadataProvider(builder, accessor, persistenceProvider);
|
||||
|
||||
return new JpaCountQueryCreator(tree, domainClass, builder, provider);
|
||||
return new JpaCountQueryCreator(tree, getQueryMethod().getResultProcessor().getReturnedType(), builder, provider);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -116,7 +116,7 @@ class StoredProcedureJpaQuery extends AbstractJpaQuery {
|
||||
JpaParameters parameters = getQueryMethod().getParameters();
|
||||
|
||||
return useNamedParameters && StringUtils.hasText(outputParameterName) ? //
|
||||
storedProcedureQuery.getOutputParameterValue(outputParameterName)
|
||||
storedProcedureQuery.getOutputParameterValue(outputParameterName)
|
||||
: storedProcedureQuery.getOutputParameterValue(parameters.getNumberOfParameters() + 1);
|
||||
}
|
||||
|
||||
|
||||
@@ -42,4 +42,12 @@ public class EclipseLinkMetamodelIntegrationTests extends MetamodelIntegrationTe
|
||||
@Ignore
|
||||
@Override
|
||||
public void pathToEntityIsOfBindableTypeEntityType() {}
|
||||
|
||||
/**
|
||||
* TODO: Remove, once https://bugs.eclipse.org/bugs/show_bug.cgi?id=289141 is fixed.
|
||||
*/
|
||||
@Test
|
||||
@Ignore
|
||||
@Override
|
||||
public void doesNotExposeAliasForTupleIfNoneDefined() {}
|
||||
}
|
||||
|
||||
@@ -35,4 +35,12 @@ public class HibernateMetamodelIntegrationTests extends MetamodelIntegrationTest
|
||||
@Ignore
|
||||
@Override
|
||||
public void considersOneToOneAttributeAnAssociation() {}
|
||||
|
||||
/**
|
||||
* @see https://hibernate.atlassian.net/browse/HHH-10341
|
||||
*/
|
||||
@Test
|
||||
@Ignore
|
||||
@Override
|
||||
public void doesNotExposeAliasForTupleIfNoneDefined() {}
|
||||
}
|
||||
|
||||
@@ -15,12 +15,17 @@
|
||||
*/
|
||||
package org.springframework.data.jpa.infrastructure;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.*;
|
||||
import static org.hamcrest.Matchers.*;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import javax.persistence.EntityManager;
|
||||
import javax.persistence.PersistenceContext;
|
||||
import javax.persistence.Query;
|
||||
import javax.persistence.Tuple;
|
||||
import javax.persistence.TupleElement;
|
||||
import javax.persistence.TypedQuery;
|
||||
import javax.persistence.criteria.CriteriaBuilder;
|
||||
import javax.persistence.criteria.CriteriaQuery;
|
||||
import javax.persistence.criteria.Path;
|
||||
@@ -35,6 +40,7 @@ import org.junit.runner.RunWith;
|
||||
import org.springframework.data.jpa.domain.sample.User;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
/**
|
||||
* @author Oliver Gierke
|
||||
@@ -74,4 +80,23 @@ public abstract class MetamodelIntegrationTests {
|
||||
|
||||
assertThat(query.getParameter(1), is(notNullValue()));
|
||||
}
|
||||
|
||||
@Test
|
||||
@Transactional
|
||||
public void doesNotExposeAliasForTupleIfNoneDefined() {
|
||||
|
||||
User user = new User();
|
||||
user.setFirstname("Dave");
|
||||
user.setEmailAddress("email");
|
||||
|
||||
em.persist(user);
|
||||
|
||||
TypedQuery<Tuple> query = em.createQuery("SELECT u.firstname from User u", Tuple.class);
|
||||
|
||||
List<Tuple> result = query.getResultList();
|
||||
List<TupleElement<?>> elements = result.get(0).getElements();
|
||||
|
||||
assertThat(elements, hasSize(1));
|
||||
assertThat(elements.get(0).getAlias(), is(nullValue()));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -31,4 +31,12 @@ public class OpenJpaMetamodelIntegrationTests extends MetamodelIntegrationTests
|
||||
@Ignore
|
||||
@Override
|
||||
public void canAccessParametersByIndexForNativeQueries() {}
|
||||
|
||||
/**
|
||||
* TODO: Remove once https://issues.apache.org/jira/browse/OPENJPA-2618 is fixed.
|
||||
*/
|
||||
@Test
|
||||
@Ignore
|
||||
@Override
|
||||
public void doesNotExposeAliasForTupleIfNoneDefined() {}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2008-2011 the original author or authors.
|
||||
* Copyright 2008-2015 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -35,11 +35,11 @@ import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.data.jpa.domain.sample.User;
|
||||
import org.springframework.data.jpa.provider.PersistenceProvider;
|
||||
import org.springframework.data.jpa.provider.QueryExtractor;
|
||||
import org.springframework.data.jpa.repository.EntityGraph;
|
||||
import org.springframework.data.jpa.repository.EntityGraph.EntityGraphType;
|
||||
import org.springframework.data.jpa.repository.Lock;
|
||||
import org.springframework.data.jpa.repository.QueryHints;
|
||||
import org.springframework.data.projection.SpelAwareProxyProjectionFactory;
|
||||
import org.springframework.data.repository.Repository;
|
||||
import org.springframework.data.repository.core.support.DefaultRepositoryMetadata;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
@@ -75,10 +75,7 @@ public class AbstractJpaQueryTests {
|
||||
@Test
|
||||
public void addsHintsToQueryObject() throws Exception {
|
||||
|
||||
Method method = SampleRepository.class.getMethod("findByLastname", String.class);
|
||||
QueryExtractor provider = PersistenceProvider.fromEntityManager(em);
|
||||
JpaQueryMethod queryMethod = new JpaQueryMethod(method, new DefaultRepositoryMetadata(SampleRepository.class),
|
||||
provider);
|
||||
JpaQueryMethod queryMethod = getMethod("findByLastname", String.class);
|
||||
|
||||
AbstractJpaQuery jpaQuery = new DummyJpaQuery(queryMethod, em);
|
||||
|
||||
@@ -96,11 +93,7 @@ public class AbstractJpaQueryTests {
|
||||
@Test
|
||||
public void skipsHintsForCountQueryIfConfigured() throws Exception {
|
||||
|
||||
Method method = SampleRepository.class.getMethod("findByFirstname", String.class);
|
||||
QueryExtractor provider = PersistenceProvider.fromEntityManager(em);
|
||||
JpaQueryMethod queryMethod = new JpaQueryMethod(method, new DefaultRepositoryMetadata(SampleRepository.class),
|
||||
provider);
|
||||
|
||||
JpaQueryMethod queryMethod = getMethod("findByFirstname", String.class);
|
||||
AbstractJpaQuery jpaQuery = new DummyJpaQuery(queryMethod, em);
|
||||
|
||||
Query result = jpaQuery.createQuery(new Object[] { "Dave" });
|
||||
@@ -118,10 +111,7 @@ public class AbstractJpaQueryTests {
|
||||
|
||||
when(query.setLockMode(any(LockModeType.class))).thenReturn(query);
|
||||
|
||||
Method method = SampleRepository.class.getMethod("findOneLocked", Integer.class);
|
||||
QueryExtractor provider = PersistenceProvider.fromEntityManager(em);
|
||||
JpaQueryMethod queryMethod = new JpaQueryMethod(method, new DefaultRepositoryMetadata(SampleRepository.class),
|
||||
provider);
|
||||
JpaQueryMethod queryMethod = getMethod("findOneLocked", Integer.class);
|
||||
|
||||
AbstractJpaQuery jpaQuery = new DummyJpaQuery(queryMethod, em);
|
||||
Query result = jpaQuery.createQuery(new Object[] { Integer.valueOf(1) });
|
||||
@@ -137,10 +127,7 @@ public class AbstractJpaQueryTests {
|
||||
|
||||
Assume.assumeTrue(currentEntityManagerIsAJpa21EntityManager(em));
|
||||
|
||||
Method findAllMethod = SampleRepository.class.getMethod("findAll");
|
||||
QueryExtractor provider = PersistenceProvider.fromEntityManager(em);
|
||||
JpaQueryMethod queryMethod = new JpaQueryMethod(findAllMethod,
|
||||
new DefaultRepositoryMetadata(SampleRepository.class), provider);
|
||||
JpaQueryMethod queryMethod = getMethod("findAll");
|
||||
|
||||
javax.persistence.EntityGraph<?> entityGraph = em.getEntityGraph("User.overview");
|
||||
|
||||
@@ -159,10 +146,7 @@ public class AbstractJpaQueryTests {
|
||||
|
||||
Assume.assumeTrue(currentEntityManagerIsAJpa21EntityManager(em));
|
||||
|
||||
Method getByIdMethod = SampleRepository.class.getMethod("getById", Integer.class);
|
||||
QueryExtractor provider = PersistenceProvider.fromEntityManager(em);
|
||||
JpaQueryMethod queryMethod = new JpaQueryMethod(getByIdMethod,
|
||||
new DefaultRepositoryMetadata(SampleRepository.class), provider);
|
||||
JpaQueryMethod queryMethod = getMethod("getById", Integer.class);
|
||||
|
||||
javax.persistence.EntityGraph<?> entityGraph = em.getEntityGraph("User.detail");
|
||||
|
||||
@@ -172,6 +156,15 @@ public class AbstractJpaQueryTests {
|
||||
verify(result).setHint("javax.persistence.loadgraph", entityGraph);
|
||||
}
|
||||
|
||||
private JpaQueryMethod getMethod(String name, Class<?>... parameterTypes) throws Exception {
|
||||
|
||||
Method method = SampleRepository.class.getMethod(name, parameterTypes);
|
||||
PersistenceProvider persistenceProvider = PersistenceProvider.fromEntityManager(em);
|
||||
|
||||
return new JpaQueryMethod(method, new DefaultRepositoryMetadata(SampleRepository.class),
|
||||
new SpelAwareProxyProjectionFactory(), persistenceProvider);
|
||||
}
|
||||
|
||||
interface SampleRepository extends Repository<User, Integer> {
|
||||
|
||||
@QueryHints({ @QueryHint(name = "foo", value = "bar") })
|
||||
|
||||
@@ -37,6 +37,7 @@ import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.data.jpa.domain.sample.User;
|
||||
import org.springframework.data.jpa.provider.QueryExtractor;
|
||||
import org.springframework.data.jpa.repository.Query;
|
||||
import org.springframework.data.projection.ProjectionFactory;
|
||||
import org.springframework.data.repository.Repository;
|
||||
import org.springframework.data.repository.core.NamedQueries;
|
||||
import org.springframework.data.repository.core.RepositoryMetadata;
|
||||
@@ -60,6 +61,7 @@ public class JpaQueryLookupStrategyUnitTests {
|
||||
@Mock EntityManagerFactory emf;
|
||||
@Mock QueryExtractor extractor;
|
||||
@Mock NamedQueries namedQueries;
|
||||
@Mock ProjectionFactory projectionFactory;
|
||||
|
||||
public @Rule ExpectedException exception = ExpectedException.none();
|
||||
|
||||
@@ -85,7 +87,7 @@ public class JpaQueryLookupStrategyUnitTests {
|
||||
when(em.createQuery(anyString())).thenThrow(reference);
|
||||
|
||||
try {
|
||||
strategy.resolveQuery(method, metadata, namedQueries);
|
||||
strategy.resolveQuery(method, metadata, projectionFactory, namedQueries);
|
||||
} catch (Exception e) {
|
||||
assertThat(e, is(instanceOf(IllegalArgumentException.class)));
|
||||
assertThat(e.getCause(), is(reference));
|
||||
@@ -107,7 +109,7 @@ public class JpaQueryLookupStrategyUnitTests {
|
||||
exception.expectMessage("Cannot use native queries with dynamic sorting and/or pagination in method");
|
||||
exception.expectMessage(method.toString());
|
||||
|
||||
strategy.resolveQuery(method, metadata, namedQueries);
|
||||
strategy.resolveQuery(method, metadata, projectionFactory, namedQueries);
|
||||
}
|
||||
|
||||
interface UserRepository extends Repository<User, Long> {
|
||||
|
||||
@@ -17,6 +17,7 @@ package org.springframework.data.jpa.repository.query;
|
||||
|
||||
import static org.hamcrest.Matchers.*;
|
||||
import static org.junit.Assert.*;
|
||||
import static org.mockito.Matchers.any;
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
@@ -45,6 +46,9 @@ import org.springframework.data.jpa.repository.Modifying;
|
||||
import org.springframework.data.jpa.repository.Query;
|
||||
import org.springframework.data.jpa.repository.QueryHints;
|
||||
import org.springframework.data.jpa.repository.sample.UserRepository;
|
||||
import org.springframework.data.projection.ProjectionFactory;
|
||||
import org.springframework.data.projection.SpelAwareProxyProjectionFactory;
|
||||
import org.springframework.data.repository.Repository;
|
||||
import org.springframework.data.repository.core.RepositoryMetadata;
|
||||
import org.springframework.data.repository.core.support.DefaultRepositoryMetadata;
|
||||
import org.springframework.data.repository.query.Param;
|
||||
@@ -64,10 +68,10 @@ public class JpaQueryMethodUnitTests {
|
||||
|
||||
@Mock QueryExtractor extractor;
|
||||
@Mock RepositoryMetadata metadata;
|
||||
ProjectionFactory factory = new SpelAwareProxyProjectionFactory();
|
||||
|
||||
Method repositoryMethod, invalidReturnType, pageableAndSort, pageableTwice, sortableTwice, modifyingMethod,
|
||||
nativeQuery, namedQuery, findWithLockMethod, invalidNamedParameter, findsProjections, findsProjection,
|
||||
withMetaAnnotation, queryMethodWithCustomEntityFetchGraph;
|
||||
Method invalidReturnType, pageableAndSort, pageableTwice, sortableTwice, findWithLockMethod, findsProjections,
|
||||
findsProjection, queryMethodWithCustomEntityFetchGraph;
|
||||
|
||||
/**
|
||||
* @throws Exception
|
||||
@@ -75,35 +79,25 @@ public class JpaQueryMethodUnitTests {
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
|
||||
repositoryMethod = UserRepository.class.getMethod("findByLastname", String.class);
|
||||
|
||||
invalidReturnType = InvalidRepository.class.getMethod(METHOD_NAME, String.class, Pageable.class);
|
||||
pageableAndSort = InvalidRepository.class.getMethod(METHOD_NAME, String.class, Pageable.class, Sort.class);
|
||||
pageableTwice = InvalidRepository.class.getMethod(METHOD_NAME, String.class, Pageable.class, Pageable.class);
|
||||
|
||||
sortableTwice = InvalidRepository.class.getMethod(METHOD_NAME, String.class, Sort.class, Sort.class);
|
||||
modifyingMethod = UserRepository.class.getMethod("renameAllUsersTo", String.class);
|
||||
|
||||
nativeQuery = ValidRepository.class.getMethod("findByLastname", String.class);
|
||||
namedQuery = ValidRepository.class.getMethod("findByNamedQuery");
|
||||
|
||||
findWithLockMethod = ValidRepository.class.getMethod("findOneLocked", Integer.class);
|
||||
invalidNamedParameter = InvalidRepository.class.getMethod("findByAnnotatedQuery", String.class);
|
||||
|
||||
findsProjections = ValidRepository.class.getMethod("findsProjections");
|
||||
findsProjection = ValidRepository.class.getMethod("findsProjection");
|
||||
|
||||
withMetaAnnotation = ValidRepository.class.getMethod("withMetaAnnotation");
|
||||
|
||||
queryMethodWithCustomEntityFetchGraph = ValidRepository.class.getMethod("queryMethodWithCustomEntityFetchGraph",
|
||||
Integer.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testname() {
|
||||
public void testname() throws Exception {
|
||||
|
||||
JpaQueryMethod method = new JpaQueryMethod(repositoryMethod, new DefaultRepositoryMetadata(UserRepository.class),
|
||||
extractor);
|
||||
JpaQueryMethod method = getQueryMethod(UserRepository.class, "findByLastname", String.class);
|
||||
|
||||
assertEquals("User.findByLastname", method.getNamedQueryName());
|
||||
assertThat(method.isCollectionQuery(), is(true));
|
||||
@@ -114,62 +108,61 @@ public class JpaQueryMethodUnitTests {
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void preventsNullRepositoryMethod() {
|
||||
|
||||
new JpaQueryMethod(null, metadata, extractor);
|
||||
new JpaQueryMethod(null, metadata, factory, extractor);
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void preventsNullQueryExtractor() {
|
||||
public void preventsNullQueryExtractor() throws Exception {
|
||||
|
||||
new JpaQueryMethod(repositoryMethod, metadata, null);
|
||||
Method method = UserRepository.class.getMethod("findByLastname", String.class);
|
||||
new JpaQueryMethod(method, metadata, factory, null);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void returnsCorrectName() {
|
||||
public void returnsCorrectName() throws Exception {
|
||||
|
||||
JpaQueryMethod method = new JpaQueryMethod(repositoryMethod, metadata, extractor);
|
||||
assertEquals(repositoryMethod.getName(), method.getName());
|
||||
JpaQueryMethod method = getQueryMethod(UserRepository.class, "findByLastname", String.class);
|
||||
assertThat(method.getName(), is("findByLastname"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void returnsQueryIfAvailable() throws Exception {
|
||||
|
||||
JpaQueryMethod method = new JpaQueryMethod(repositoryMethod, metadata, extractor);
|
||||
JpaQueryMethod method = getQueryMethod(UserRepository.class, "findByLastname", String.class);
|
||||
assertThat(method.getAnnotatedQuery(), is(nullValue()));
|
||||
|
||||
assertNull(method.getAnnotatedQuery());
|
||||
|
||||
Method repositoryMethod = UserRepository.class.getMethod("findByAnnotatedQuery", String.class);
|
||||
|
||||
assertNotNull(new JpaQueryMethod(repositoryMethod, metadata, extractor).getAnnotatedQuery());
|
||||
method = getQueryMethod(UserRepository.class, "findByAnnotatedQuery", String.class);
|
||||
assertThat(method.getAnnotatedQuery(), is(notNullValue()));
|
||||
}
|
||||
|
||||
@Test(expected = IllegalStateException.class)
|
||||
public void rejectsInvalidReturntypeOnPagebleFinder() {
|
||||
|
||||
new JpaQueryMethod(invalidReturnType, metadata, extractor);
|
||||
new JpaQueryMethod(invalidReturnType, metadata, factory, extractor);
|
||||
}
|
||||
|
||||
@Test(expected = IllegalStateException.class)
|
||||
public void rejectsPageableAndSortInFinderMethod() {
|
||||
|
||||
new JpaQueryMethod(pageableAndSort, metadata, extractor);
|
||||
new JpaQueryMethod(pageableAndSort, metadata, factory, extractor);
|
||||
}
|
||||
|
||||
@Test(expected = IllegalStateException.class)
|
||||
public void rejectsTwoPageableParameters() {
|
||||
|
||||
new JpaQueryMethod(pageableTwice, metadata, extractor);
|
||||
new JpaQueryMethod(pageableTwice, metadata, factory, extractor);
|
||||
}
|
||||
|
||||
@Test(expected = IllegalStateException.class)
|
||||
public void rejectsTwoSortableParameters() {
|
||||
|
||||
new JpaQueryMethod(sortableTwice, metadata, extractor);
|
||||
new JpaQueryMethod(sortableTwice, metadata, factory, extractor);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void recognizesModifyingMethod() {
|
||||
public void recognizesModifyingMethod() throws Exception {
|
||||
|
||||
JpaQueryMethod method = new JpaQueryMethod(modifyingMethod, metadata, extractor);
|
||||
JpaQueryMethod method = getQueryMethod(UserRepository.class, "renameAllUsersTo", String.class);
|
||||
assertTrue(method.isModifyingQuery());
|
||||
}
|
||||
|
||||
@@ -178,7 +171,7 @@ public class JpaQueryMethodUnitTests {
|
||||
|
||||
Method method = InvalidRepository.class.getMethod("updateMethod", String.class, Pageable.class);
|
||||
|
||||
new JpaQueryMethod(method, metadata, extractor);
|
||||
new JpaQueryMethod(method, metadata, factory, extractor);
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
@@ -186,13 +179,13 @@ public class JpaQueryMethodUnitTests {
|
||||
|
||||
Method method = InvalidRepository.class.getMethod("updateMethod", String.class, Sort.class);
|
||||
|
||||
new JpaQueryMethod(method, metadata, extractor);
|
||||
new JpaQueryMethod(method, metadata, factory, extractor);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void discoversHintsCorrectly() {
|
||||
public void discoversHintsCorrectly() throws Exception {
|
||||
|
||||
JpaQueryMethod method = new JpaQueryMethod(repositoryMethod, metadata, extractor);
|
||||
JpaQueryMethod method = getQueryMethod(UserRepository.class, "findByLastname", String.class);
|
||||
List<QueryHint> hints = method.getHints();
|
||||
|
||||
assertNotNull(hints);
|
||||
@@ -200,20 +193,28 @@ public class JpaQueryMethodUnitTests {
|
||||
assertThat(hints.get(0).value(), is("bar"));
|
||||
}
|
||||
|
||||
private JpaQueryMethod getQueryMethod(Class<?> repositoryInterface, String methodName, Class<?>... parameterTypes)
|
||||
throws Exception {
|
||||
|
||||
Method method = repositoryInterface.getMethod(methodName, parameterTypes);
|
||||
DefaultRepositoryMetadata repositoryMetadata = new DefaultRepositoryMetadata(repositoryInterface);
|
||||
return new JpaQueryMethod(method, repositoryMetadata, factory, extractor);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void calculatesNamedQueryNamesCorrectly() throws SecurityException, NoSuchMethodException {
|
||||
public void calculatesNamedQueryNamesCorrectly() throws Exception {
|
||||
|
||||
RepositoryMetadata metadata = new DefaultRepositoryMetadata(UserRepository.class);
|
||||
|
||||
JpaQueryMethod queryMethod = new JpaQueryMethod(repositoryMethod, metadata, extractor);
|
||||
JpaQueryMethod queryMethod = getQueryMethod(UserRepository.class, "findByLastname", String.class);
|
||||
assertThat(queryMethod.getNamedQueryName(), is("User.findByLastname"));
|
||||
|
||||
Method method = UserRepository.class.getMethod("renameAllUsersTo", String.class);
|
||||
queryMethod = new JpaQueryMethod(method, metadata, extractor);
|
||||
queryMethod = new JpaQueryMethod(method, metadata, factory, extractor);
|
||||
assertThat(queryMethod.getNamedQueryName(), is("User.renameAllUsersTo"));
|
||||
|
||||
method = UserRepository.class.getMethod("findSpecialUsersByLastname", String.class);
|
||||
queryMethod = new JpaQueryMethod(method, metadata, extractor);
|
||||
queryMethod = new JpaQueryMethod(method, metadata, factory, extractor);
|
||||
assertThat(queryMethod.getNamedQueryName(), is("SpecialUser.findSpecialUsersByLastname"));
|
||||
}
|
||||
|
||||
@@ -221,9 +222,9 @@ public class JpaQueryMethodUnitTests {
|
||||
* @see DATAJPA-117
|
||||
*/
|
||||
@Test
|
||||
public void discoversNativeQuery() {
|
||||
public void discoversNativeQuery() throws Exception {
|
||||
|
||||
JpaQueryMethod method = new JpaQueryMethod(nativeQuery, metadata, extractor);
|
||||
JpaQueryMethod method = getQueryMethod(ValidRepository.class, "findByLastname", String.class);
|
||||
assertThat(method.isNativeQuery(), is(true));
|
||||
}
|
||||
|
||||
@@ -231,8 +232,9 @@ public class JpaQueryMethodUnitTests {
|
||||
* @see DATAJPA-129
|
||||
*/
|
||||
@Test
|
||||
public void considersAnnotatedNamedQueryName() {
|
||||
JpaQueryMethod queryMethod = new JpaQueryMethod(namedQuery, metadata, extractor);
|
||||
public void considersAnnotatedNamedQueryName() throws Exception {
|
||||
|
||||
JpaQueryMethod queryMethod = getQueryMethod(ValidRepository.class, "findByNamedQuery");
|
||||
assertThat(queryMethod.getNamedQueryName(), is("HateoasAwareSpringDataWebConfiguration.bar"));
|
||||
}
|
||||
|
||||
@@ -242,7 +244,7 @@ public class JpaQueryMethodUnitTests {
|
||||
@Test
|
||||
public void discoversLockModeCorrectly() throws Exception {
|
||||
|
||||
JpaQueryMethod method = new JpaQueryMethod(findWithLockMethod, metadata, extractor);
|
||||
JpaQueryMethod method = getQueryMethod(ValidRepository.class, "findOneLocked", Integer.class);
|
||||
LockModeType lockMode = method.getLockModeType();
|
||||
|
||||
assertEquals(LockModeType.PESSIMISTIC_WRITE, lockMode);
|
||||
@@ -252,12 +254,9 @@ public class JpaQueryMethodUnitTests {
|
||||
* @see DATAJPA-142
|
||||
*/
|
||||
@Test
|
||||
@SuppressWarnings({ "unchecked", "rawtypes" })
|
||||
public void returnsDefaultCountQueryName() {
|
||||
public void returnsDefaultCountQueryName() throws Exception {
|
||||
|
||||
when(metadata.getReturnedDomainClass(repositoryMethod)).thenReturn((Class) User.class);
|
||||
|
||||
JpaQueryMethod method = new JpaQueryMethod(repositoryMethod, metadata, extractor);
|
||||
JpaQueryMethod method = getQueryMethod(UserRepository.class, "findByLastname", String.class);
|
||||
assertThat(method.getNamedCountQueryName(), is("User.findByLastname.count"));
|
||||
}
|
||||
|
||||
@@ -265,9 +264,9 @@ public class JpaQueryMethodUnitTests {
|
||||
* @see DATAJPA-142
|
||||
*/
|
||||
@Test
|
||||
public void returnsDefaultCountQueryNameBasedOnConfiguredNamedQueryName() {
|
||||
public void returnsDefaultCountQueryNameBasedOnConfiguredNamedQueryName() throws Exception {
|
||||
|
||||
JpaQueryMethod method = new JpaQueryMethod(namedQuery, metadata, extractor);
|
||||
JpaQueryMethod method = getQueryMethod(ValidRepository.class, "findByNamedQuery");
|
||||
assertThat(method.getNamedCountQueryName(), is("HateoasAwareSpringDataWebConfiguration.bar.count"));
|
||||
}
|
||||
|
||||
@@ -275,10 +274,10 @@ public class JpaQueryMethodUnitTests {
|
||||
* @see DATAJPA-185
|
||||
*/
|
||||
@Test
|
||||
public void rejectsInvalidNamedParameter() {
|
||||
public void rejectsInvalidNamedParameter() throws Exception {
|
||||
|
||||
try {
|
||||
new JpaQueryMethod(invalidNamedParameter, metadata, extractor);
|
||||
getQueryMethod(InvalidRepository.class, "findByAnnotatedQuery", String.class);
|
||||
fail();
|
||||
} catch (IllegalStateException e) {
|
||||
// Parameter from query
|
||||
@@ -301,17 +300,17 @@ public class JpaQueryMethodUnitTests {
|
||||
when(metadata.getReturnedDomainClass(findsProjections)).thenReturn((Class) Integer.class);
|
||||
when(metadata.getReturnedDomainClass(findsProjection)).thenReturn((Class) Integer.class);
|
||||
|
||||
assertThat(new JpaQueryMethod(findsProjections, metadata, extractor).isQueryForEntity(), is(false));
|
||||
assertThat(new JpaQueryMethod(findsProjection, metadata, extractor).isQueryForEntity(), is(false));
|
||||
assertThat(new JpaQueryMethod(findsProjections, metadata, factory, extractor).isQueryForEntity(), is(false));
|
||||
assertThat(new JpaQueryMethod(findsProjection, metadata, factory, extractor).isQueryForEntity(), is(false));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAJPA-345
|
||||
*/
|
||||
@Test
|
||||
public void detectsLockAndQueryHintsOnIfUsedAsMetaAnnotation() {
|
||||
public void detectsLockAndQueryHintsOnIfUsedAsMetaAnnotation() throws Exception {
|
||||
|
||||
JpaQueryMethod method = new JpaQueryMethod(withMetaAnnotation, metadata, extractor);
|
||||
JpaQueryMethod method = getQueryMethod(ValidRepository.class, "withMetaAnnotation");
|
||||
|
||||
assertThat(method.getLockModeType(), is(LockModeType.OPTIMISTIC_FORCE_INCREMENT));
|
||||
assertThat(method.getHints(), hasSize(1));
|
||||
@@ -324,11 +323,11 @@ public class JpaQueryMethodUnitTests {
|
||||
*/
|
||||
@Test
|
||||
public void shouldStoreJpa21FetchGraphInformationAsHint() {
|
||||
|
||||
|
||||
doReturn(User.class).when(metadata).getDomainType();
|
||||
doReturn(User.class).when(metadata).getReturnedDomainClass(queryMethodWithCustomEntityFetchGraph);
|
||||
|
||||
JpaQueryMethod method = new JpaQueryMethod(queryMethodWithCustomEntityFetchGraph, metadata, extractor);
|
||||
JpaQueryMethod method = new JpaQueryMethod(queryMethodWithCustomEntityFetchGraph, metadata, factory, extractor);
|
||||
|
||||
assertThat(method.getEntityGraph(), is(notNullValue()));
|
||||
assertThat(method.getEntityGraph().getName(), is("User.propertyLoadPath"));
|
||||
@@ -342,9 +341,10 @@ public class JpaQueryMethodUnitTests {
|
||||
public void shouldFindEntityGraphAnnotationOnOverriddenSimpleJpaRepositoryMethod() throws Exception {
|
||||
|
||||
doReturn(User.class).when(metadata).getDomainType();
|
||||
doReturn(User.class).when(metadata).getReturnedDomainClass((Method)any());
|
||||
|
||||
JpaQueryMethod method = new JpaQueryMethod(JpaRepositoryOverride.class.getMethod("findAll"), metadata, extractor);
|
||||
doReturn(User.class).when(metadata).getReturnedDomainClass((Method) any());
|
||||
|
||||
JpaQueryMethod method = new JpaQueryMethod(JpaRepositoryOverride.class.getMethod("findAll"), metadata, factory,
|
||||
extractor);
|
||||
|
||||
assertThat(method.getEntityGraph(), is(notNullValue()));
|
||||
assertThat(method.getEntityGraph().getName(), is("User.detail"));
|
||||
@@ -358,15 +358,16 @@ public class JpaQueryMethodUnitTests {
|
||||
public void shouldFindEntityGraphAnnotationOnOverriddenSimpleJpaRepositoryMethodFindOne() throws Exception {
|
||||
|
||||
doReturn(User.class).when(metadata).getDomainType();
|
||||
doReturn(User.class).when(metadata).getReturnedDomainClass((Method)any());
|
||||
|
||||
JpaQueryMethod method = new JpaQueryMethod(JpaRepositoryOverride.class.getMethod("findOne", Long.class), metadata, extractor);
|
||||
doReturn(User.class).when(metadata).getReturnedDomainClass((Method) any());
|
||||
|
||||
JpaQueryMethod method = new JpaQueryMethod(JpaRepositoryOverride.class.getMethod("findOne", Long.class), metadata,
|
||||
factory, extractor);
|
||||
|
||||
assertThat(method.getEntityGraph(), is(notNullValue()));
|
||||
assertThat(method.getEntityGraph().getName(), is("User.detail"));
|
||||
assertThat(method.getEntityGraph().getType(), is(EntityGraphType.FETCH));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* DATAJPA-696
|
||||
*/
|
||||
@@ -374,9 +375,10 @@ public class JpaQueryMethodUnitTests {
|
||||
public void shouldFindEntityGraphAnnotationOnQueryMethodGetOneByWithDerivedName() throws Exception {
|
||||
|
||||
doReturn(User.class).when(metadata).getDomainType();
|
||||
doReturn(User.class).when(metadata).getReturnedDomainClass((Method)any());
|
||||
|
||||
JpaQueryMethod method = new JpaQueryMethod(JpaRepositoryOverride.class.getMethod("getOneById", Long.class), metadata, extractor);
|
||||
doReturn(User.class).when(metadata).getReturnedDomainClass((Method) any());
|
||||
|
||||
JpaQueryMethod method = new JpaQueryMethod(JpaRepositoryOverride.class.getMethod("getOneById", Long.class),
|
||||
metadata, factory, extractor);
|
||||
|
||||
assertThat(method.getEntityGraph(), is(notNullValue()));
|
||||
assertThat(method.getEntityGraph().getName(), is("User.getOneById"));
|
||||
@@ -388,9 +390,7 @@ public class JpaQueryMethodUnitTests {
|
||||
*/
|
||||
@Test
|
||||
public void allowsPositionalBindingEvenIfParametersAreNamed() throws Exception {
|
||||
|
||||
new JpaQueryMethod(ValidRepository.class.getMethod("queryWithPositionalBinding", String.class), metadata,
|
||||
extractor);
|
||||
getQueryMethod(ValidRepository.class, "queryWithPositionalBinding", String.class);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -398,7 +398,7 @@ public class JpaQueryMethodUnitTests {
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
static interface InvalidRepository {
|
||||
static interface InvalidRepository extends Repository<User, Long> {
|
||||
|
||||
// Invalid return type
|
||||
User findByFirstname(String firstname, Pageable pageable);
|
||||
@@ -429,7 +429,7 @@ public class JpaQueryMethodUnitTests {
|
||||
List<User> findByAnnotatedQuery(@Param("param") String param);
|
||||
}
|
||||
|
||||
static interface ValidRepository {
|
||||
static interface ValidRepository extends Repository<User, Long> {
|
||||
|
||||
@Query(value = "query", nativeQuery = true)
|
||||
List<User> findByLastname(String lastname);
|
||||
@@ -472,7 +472,7 @@ public class JpaQueryMethodUnitTests {
|
||||
*/
|
||||
@EntityGraph("User.detail")
|
||||
User findOne(Long id);
|
||||
|
||||
|
||||
/**
|
||||
* DATAJPA-696
|
||||
*/
|
||||
|
||||
@@ -31,6 +31,8 @@ import org.mockito.runners.MockitoJUnitRunner;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.data.jpa.provider.QueryExtractor;
|
||||
import org.springframework.data.projection.ProjectionFactory;
|
||||
import org.springframework.data.projection.SpelAwareProxyProjectionFactory;
|
||||
import org.springframework.data.repository.core.RepositoryMetadata;
|
||||
import org.springframework.data.repository.query.QueryCreationException;
|
||||
|
||||
@@ -47,6 +49,7 @@ public class NamedQueryUnitTests {
|
||||
@Mock QueryExtractor extractor;
|
||||
@Mock EntityManager em;
|
||||
@Mock EntityManagerFactory emf;
|
||||
ProjectionFactory projectionFactory = new SpelAwareProxyProjectionFactory();
|
||||
|
||||
Method method;
|
||||
|
||||
@@ -57,7 +60,7 @@ public class NamedQueryUnitTests {
|
||||
method = SampleRepository.class.getMethod("foo", Pageable.class);
|
||||
when(metadata.getDomainType()).thenReturn((Class) String.class);
|
||||
when(metadata.getReturnedDomainClass(method)).thenReturn((Class) String.class);
|
||||
|
||||
|
||||
when(em.getEntityManagerFactory()).thenReturn(emf);
|
||||
when(emf.createEntityManager()).thenReturn(em);
|
||||
}
|
||||
@@ -66,7 +69,7 @@ public class NamedQueryUnitTests {
|
||||
public void rejectsPersistenceProviderIfIncapableOfExtractingQueriesAndPagebleBeingUsed() {
|
||||
|
||||
when(extractor.canExtractQuery()).thenReturn(false);
|
||||
JpaQueryMethod queryMethod = new JpaQueryMethod(method, metadata, extractor);
|
||||
JpaQueryMethod queryMethod = new JpaQueryMethod(method, metadata, projectionFactory, extractor);
|
||||
|
||||
when(em.createNamedQuery(queryMethod.getNamedCountQueryName())).thenThrow(new IllegalArgumentException());
|
||||
NamedQuery.lookupFrom(queryMethod, em);
|
||||
@@ -79,7 +82,7 @@ public class NamedQueryUnitTests {
|
||||
public void doesNotRejectPersistenceProviderIfNamedCountQueryIsAvailable() {
|
||||
|
||||
when(extractor.canExtractQuery()).thenReturn(false);
|
||||
JpaQueryMethod queryMethod = new JpaQueryMethod(method, metadata, extractor);
|
||||
JpaQueryMethod queryMethod = new JpaQueryMethod(method, metadata, projectionFactory, extractor);
|
||||
|
||||
when(em.createNamedQuery(queryMethod.getNamedCountQueryName())).thenReturn(null);
|
||||
NamedQuery query = (NamedQuery) NamedQuery.lookupFrom(queryMethod, em);
|
||||
|
||||
@@ -44,6 +44,7 @@ import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.data.jpa.domain.sample.User;
|
||||
import org.springframework.data.jpa.provider.PersistenceProvider;
|
||||
import org.springframework.data.jpa.repository.Temporal;
|
||||
import org.springframework.data.projection.SpelAwareProxyProjectionFactory;
|
||||
import org.springframework.data.repository.Repository;
|
||||
import org.springframework.data.repository.core.support.DefaultRepositoryMetadata;
|
||||
import org.springframework.data.repository.query.Param;
|
||||
@@ -72,9 +73,7 @@ public class PartTreeJpaQueryIntegrationTests {
|
||||
@Test
|
||||
public void test() throws Exception {
|
||||
|
||||
Method method = UserRepository.class.getMethod("findByFirstname", String.class, Pageable.class);
|
||||
JpaQueryMethod queryMethod = new JpaQueryMethod(method, new DefaultRepositoryMetadata(UserRepository.class),
|
||||
PersistenceProvider.fromEntityManager(entityManager));
|
||||
JpaQueryMethod queryMethod = getQueryMethod("findByFirstname", String.class, Pageable.class);
|
||||
PartTreeJpaQuery jpaQuery = new PartTreeJpaQuery(queryMethod, entityManager);
|
||||
|
||||
jpaQuery.createQuery(new Object[] { "Matthews", new PageRequest(0, 1) });
|
||||
@@ -101,9 +100,7 @@ public class PartTreeJpaQueryIntegrationTests {
|
||||
@Test
|
||||
public void recreatesQueryIfNullValueIsGiven() throws Exception {
|
||||
|
||||
Method method = UserRepository.class.getMethod("findByFirstname", String.class, Pageable.class);
|
||||
JpaQueryMethod queryMethod = new JpaQueryMethod(method, new DefaultRepositoryMetadata(UserRepository.class),
|
||||
PersistenceProvider.fromEntityManager(entityManager));
|
||||
JpaQueryMethod queryMethod = getQueryMethod("findByFirstname", String.class, Pageable.class);
|
||||
PartTreeJpaQuery jpaQuery = new PartTreeJpaQuery(queryMethod, entityManager);
|
||||
|
||||
Query query = jpaQuery.createQuery(new Object[] { "Matthews", new PageRequest(0, 1) });
|
||||
@@ -124,12 +121,18 @@ public class PartTreeJpaQueryIntegrationTests {
|
||||
parameterTypes[i] = values[i].getClass();
|
||||
}
|
||||
Method method = UserRepository.class.getMethod(methodName, parameterTypes);
|
||||
JpaQueryMethod queryMethod = new JpaQueryMethod(method, new DefaultRepositoryMetadata(UserRepository.class),
|
||||
PersistenceProvider.fromEntityManager(entityManager));
|
||||
JpaQueryMethod queryMethod = getQueryMethod(methodName, parameterTypes);
|
||||
PartTreeJpaQuery jpaQuery = new PartTreeJpaQuery(queryMethod, entityManager);
|
||||
|
||||
jpaQuery.createQuery(values);
|
||||
}
|
||||
|
||||
private JpaQueryMethod getQueryMethod(String methodName, Class<?>... parameterTypes) throws Exception {
|
||||
Method method = UserRepository.class.getMethod(methodName, parameterTypes);
|
||||
return new JpaQueryMethod(method, new DefaultRepositoryMetadata(UserRepository.class),
|
||||
new SpelAwareProxyProjectionFactory(), PersistenceProvider.fromEntityManager(entityManager));
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private static <T> T getValue(Object source, String path) {
|
||||
|
||||
|
||||
@@ -43,6 +43,8 @@ import org.springframework.data.jpa.domain.sample.User;
|
||||
import org.springframework.data.jpa.provider.QueryExtractor;
|
||||
import org.springframework.data.jpa.repository.Query;
|
||||
import org.springframework.data.jpa.repository.sample.UserRepository;
|
||||
import org.springframework.data.projection.ProjectionFactory;
|
||||
import org.springframework.data.projection.SpelAwareProxyProjectionFactory;
|
||||
import org.springframework.data.repository.core.RepositoryMetadata;
|
||||
import org.springframework.data.repository.query.EvaluationContextProvider;
|
||||
import org.springframework.data.repository.query.ExtensionAwareEvaluationContextProvider;
|
||||
@@ -72,6 +74,8 @@ public class SimpleJpaQueryUnitTests {
|
||||
@Mock RepositoryMetadata metadata;
|
||||
@Mock ParameterBinder binder;
|
||||
|
||||
ProjectionFactory factory = new SpelAwareProxyProjectionFactory();
|
||||
|
||||
public @Rule ExpectedException exception = ExpectedException.none();
|
||||
|
||||
@Before
|
||||
@@ -86,14 +90,14 @@ public class SimpleJpaQueryUnitTests {
|
||||
when(metadata.getReturnedDomainClass(Mockito.any(Method.class))).thenReturn((Class) User.class);
|
||||
|
||||
Method setUp = UserRepository.class.getMethod("findByLastname", String.class);
|
||||
method = new JpaQueryMethod(setUp, metadata, extractor);
|
||||
method = new JpaQueryMethod(setUp, metadata, factory, extractor);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void prefersDeclaredCountQueryOverCreatingOne() throws Exception {
|
||||
|
||||
method = new JpaQueryMethod(SimpleJpaQueryUnitTests.class.getMethod("prefersDeclaredCountQueryOverCreatingOne"),
|
||||
metadata, extractor);
|
||||
metadata, factory, extractor);
|
||||
when(em.createQuery("foo", Long.class)).thenReturn(typedQuery);
|
||||
|
||||
SimpleJpaQuery jpaQuery = new SimpleJpaQuery(method, em, "select u from User u", EVALUATION_CONTEXT_PROVIDER,
|
||||
@@ -111,7 +115,7 @@ public class SimpleJpaQueryUnitTests {
|
||||
when(em.createQuery(Mockito.anyString())).thenReturn(query);
|
||||
|
||||
Method method = UserRepository.class.getMethod("findAllPaged", Pageable.class);
|
||||
JpaQueryMethod queryMethod = new JpaQueryMethod(method, metadata, extractor);
|
||||
JpaQueryMethod queryMethod = new JpaQueryMethod(method, metadata, factory, extractor);
|
||||
|
||||
AbstractJpaQuery jpaQuery = new SimpleJpaQuery(queryMethod, em, "select u from User u", EVALUATION_CONTEXT_PROVIDER,
|
||||
PARSER);
|
||||
@@ -126,7 +130,7 @@ public class SimpleJpaQueryUnitTests {
|
||||
public void discoversNativeQuery() throws Exception {
|
||||
|
||||
Method method = SampleRepository.class.getMethod("findNativeByLastname", String.class);
|
||||
JpaQueryMethod queryMethod = new JpaQueryMethod(method, metadata, extractor);
|
||||
JpaQueryMethod queryMethod = new JpaQueryMethod(method, metadata, factory, extractor);
|
||||
AbstractJpaQuery jpaQuery = JpaQueryFactory.INSTANCE.fromQueryAnnotation(queryMethod, em,
|
||||
EVALUATION_CONTEXT_PROVIDER);
|
||||
|
||||
@@ -224,7 +228,7 @@ public class SimpleJpaQueryUnitTests {
|
||||
|
||||
private AbstractJpaQuery createJpaQuery(Method method) {
|
||||
|
||||
JpaQueryMethod queryMethod = new JpaQueryMethod(method, metadata, extractor);
|
||||
JpaQueryMethod queryMethod = new JpaQueryMethod(method, metadata, factory, extractor);
|
||||
return JpaQueryFactory.INSTANCE.fromQueryAnnotation(queryMethod, em, EVALUATION_CONTEXT_PROVIDER);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user