From 8f5f3af699311aac55f0d2c74f61761b15cfe6ec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9da=20Housni=20Alaoui?= Date: Fri, 18 Jan 2019 19:11:34 +0100 Subject: [PATCH] DATAJPA-1497 - Allow to add a special parameter type from a Spring Data JPA extension. This change allows to add a special parameter type by overriding org.springframework.data.jpa.repository.query.JpaParameters.JpaParameter.isBindable(). A "special parameter type" is a type of parameter that does not get bound to the query via the normal mechanism but gets some special treatment like `Class` or `Pageable`). Original pull request: #305. --- .../jpa/repository/query/JpaParameters.java | 5 +- .../query/JpaQueryLookupStrategy.java | 38 +++--- .../jpa/repository/query/JpaQueryMethod.java | 18 ++- .../query/JpaQueryMethodFactory.java | 39 ++++++ .../support/JpaRepositoryFactory.java | 20 ++- .../support/JpaRepositoryFactoryBean.java | 17 +++ .../CustomNonBindableJpaParametersTests.java | 126 ++++++++++++++++++ .../JpaQueryLookupStrategyUnitTests.java | 12 +- 8 files changed, 250 insertions(+), 25 deletions(-) create mode 100644 src/main/java/org/springframework/data/jpa/repository/query/JpaQueryMethodFactory.java create mode 100644 src/test/java/org/springframework/data/jpa/repository/query/CustomNonBindableJpaParametersTests.java diff --git a/src/main/java/org/springframework/data/jpa/repository/query/JpaParameters.java b/src/main/java/org/springframework/data/jpa/repository/query/JpaParameters.java index ffed62d30..cae33e279 100644 --- a/src/main/java/org/springframework/data/jpa/repository/query/JpaParameters.java +++ b/src/main/java/org/springframework/data/jpa/repository/query/JpaParameters.java @@ -33,6 +33,7 @@ import org.springframework.lang.Nullable; * * @author Thomas Darimont * @author Mark Paluch + * @author Réda Housni Alaoui */ public class JpaParameters extends Parameters { @@ -73,7 +74,7 @@ public class JpaParameters extends Parameters { * @author Thomas Darimont * @author Oliver Gierke */ - static class JpaParameter extends Parameter { + public static class JpaParameter extends Parameter { private final @Nullable Temporal annotation; private @Nullable TemporalType temporalType; @@ -83,7 +84,7 @@ public class JpaParameters extends Parameters { * * @param parameter must not be {@literal null}. */ - JpaParameter(MethodParameter parameter) { + protected JpaParameter(MethodParameter parameter) { super(parameter); diff --git a/src/main/java/org/springframework/data/jpa/repository/query/JpaQueryLookupStrategy.java b/src/main/java/org/springframework/data/jpa/repository/query/JpaQueryLookupStrategy.java index 01f6d075e..32aee712a 100644 --- a/src/main/java/org/springframework/data/jpa/repository/query/JpaQueryLookupStrategy.java +++ b/src/main/java/org/springframework/data/jpa/repository/query/JpaQueryLookupStrategy.java @@ -38,6 +38,7 @@ import org.springframework.util.Assert; * @author Oliver Gierke * @author Thomas Darimont * @author Mark Paluch + * @author Réda Housni Alaoui */ public final class JpaQueryLookupStrategy { @@ -56,17 +57,21 @@ public final class JpaQueryLookupStrategy { private final EntityManager em; private final QueryExtractor provider; + private final JpaQueryMethodFactory queryMethodFactory; /** * Creates a new {@link AbstractQueryLookupStrategy}. * * @param em * @param extractor + * @param queryMethodFactory */ - public AbstractQueryLookupStrategy(EntityManager em, QueryExtractor extractor) { + public AbstractQueryLookupStrategy(EntityManager em, QueryExtractor extractor, + JpaQueryMethodFactory queryMethodFactory) { this.em = em; this.provider = extractor; + this.queryMethodFactory = queryMethodFactory; } /* @@ -76,7 +81,7 @@ public final class JpaQueryLookupStrategy { @Override public final RepositoryQuery resolveQuery(Method method, RepositoryMetadata metadata, ProjectionFactory factory, NamedQueries namedQueries) { - return resolveQuery(new JpaQueryMethod(method, metadata, factory, provider), em, namedQueries); + return resolveQuery(queryMethodFactory.build(method, metadata, factory, provider), em, namedQueries); } protected abstract RepositoryQuery resolveQuery(JpaQueryMethod method, EntityManager em, NamedQueries namedQueries); @@ -93,10 +98,9 @@ public final class JpaQueryLookupStrategy { private final PersistenceProvider persistenceProvider; private final EscapeCharacter escape; - public CreateQueryLookupStrategy(EntityManager em, QueryExtractor extractor, EscapeCharacter escape) { - - super(em, extractor); + public CreateQueryLookupStrategy(EntityManager em, QueryExtractor extractor, EscapeCharacter escape, JpaQueryMethodFactory queryMethodFactory) { + super(em, extractor, queryMethodFactory); this.persistenceProvider = PersistenceProvider.fromEntityManager(em); this.escape = escape; } @@ -123,12 +127,13 @@ public final class JpaQueryLookupStrategy { * * @param em * @param extractor + * @param queryMethodFactory * @param evaluationContextProvider */ public DeclaredQueryLookupStrategy(EntityManager em, QueryExtractor extractor, - QueryMethodEvaluationContextProvider evaluationContextProvider) { + JpaQueryMethodFactory queryMethodFactory, QueryMethodEvaluationContextProvider evaluationContextProvider) { - super(em, extractor); + super(em, extractor, queryMethodFactory); this.evaluationContextProvider = evaluationContextProvider; } @@ -186,13 +191,15 @@ public final class JpaQueryLookupStrategy { * * @param em * @param extractor + * @param queryMethodFactory * @param createStrategy * @param lookupStrategy */ public CreateIfNotFoundQueryLookupStrategy(EntityManager em, QueryExtractor extractor, - CreateQueryLookupStrategy createStrategy, DeclaredQueryLookupStrategy lookupStrategy) { + JpaQueryMethodFactory queryMethodFactory, CreateQueryLookupStrategy createStrategy, + DeclaredQueryLookupStrategy lookupStrategy) { - super(em, extractor); + super(em, extractor, queryMethodFactory); this.createStrategy = createStrategy; this.lookupStrategy = lookupStrategy; @@ -219,12 +226,13 @@ public final class JpaQueryLookupStrategy { * @param em must not be {@literal null}. * @param key may be {@literal null}. * @param extractor must not be {@literal null}. + * @param queryMethodFactory must not be {@literal null}. * @param evaluationContextProvider must not be {@literal null}. * @param escape * @return */ public static QueryLookupStrategy create(EntityManager em, @Nullable Key key, QueryExtractor extractor, - QueryMethodEvaluationContextProvider evaluationContextProvider, EscapeCharacter escape) { + JpaQueryMethodFactory queryMethodFactory, QueryMethodEvaluationContextProvider evaluationContextProvider, EscapeCharacter escape) { Assert.notNull(em, "EntityManager must not be null!"); Assert.notNull(extractor, "QueryExtractor must not be null!"); @@ -232,13 +240,13 @@ public final class JpaQueryLookupStrategy { switch (key != null ? key : Key.CREATE_IF_NOT_FOUND) { case CREATE: - return new CreateQueryLookupStrategy(em, extractor, escape); + return new CreateQueryLookupStrategy(em, extractor, escape, queryMethodFactory); case USE_DECLARED_QUERY: - return new DeclaredQueryLookupStrategy(em, extractor, evaluationContextProvider); + return new DeclaredQueryLookupStrategy(em, extractor, queryMethodFactory, evaluationContextProvider); case CREATE_IF_NOT_FOUND: - return new CreateIfNotFoundQueryLookupStrategy(em, extractor, - new CreateQueryLookupStrategy(em, extractor, escape), - new DeclaredQueryLookupStrategy(em, extractor, evaluationContextProvider)); + return new CreateIfNotFoundQueryLookupStrategy(em, extractor,queryMethodFactory, + new CreateQueryLookupStrategy(em, extractor, escape, queryMethodFactory), + new DeclaredQueryLookupStrategy(em, extractor, queryMethodFactory, evaluationContextProvider)); default: throw new IllegalArgumentException(String.format("Unsupported query lookup strategy %s!", key)); } diff --git a/src/main/java/org/springframework/data/jpa/repository/query/JpaQueryMethod.java b/src/main/java/org/springframework/data/jpa/repository/query/JpaQueryMethod.java index 7a94fb32a..4d962c1c6 100644 --- a/src/main/java/org/springframework/data/jpa/repository/query/JpaQueryMethod.java +++ b/src/main/java/org/springframework/data/jpa/repository/query/JpaQueryMethod.java @@ -54,6 +54,7 @@ import org.springframework.util.StringUtils; * @author Nicolas Cirigliano * @author Mark Paluch * @author Сергей Цыпанов + * @author Réda Housni Alaoui */ public class JpaQueryMethod extends QueryMethod { @@ -97,7 +98,7 @@ public class JpaQueryMethod extends QueryMethod { * @param factory must not be {@literal null} * @param extractor must not be {@literal null} */ - public JpaQueryMethod(Method method, RepositoryMetadata metadata, ProjectionFactory factory, + protected JpaQueryMethod(Method method, RepositoryMetadata metadata, ProjectionFactory factory, QueryExtractor extractor) { super(method, metadata, factory); @@ -426,4 +427,19 @@ public class JpaQueryMethod extends QueryMethod { return storedProcedureAttributes; } + + public static class Factory implements JpaQueryMethodFactory { + + public static final Factory INSTANCE = new Factory(); + + private Factory() { + + } + + @Override + public JpaQueryMethod build(Method method, RepositoryMetadata metadata, ProjectionFactory factory, + QueryExtractor extractor) { + return new JpaQueryMethod(method, metadata, factory, extractor); + } + } } diff --git a/src/main/java/org/springframework/data/jpa/repository/query/JpaQueryMethodFactory.java b/src/main/java/org/springframework/data/jpa/repository/query/JpaQueryMethodFactory.java new file mode 100644 index 000000000..a9618c8a6 --- /dev/null +++ b/src/main/java/org/springframework/data/jpa/repository/query/JpaQueryMethodFactory.java @@ -0,0 +1,39 @@ +/* + * Copyright 2012-2019 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. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.data.jpa.repository.query; + +import java.lang.reflect.Method; + +import org.springframework.data.jpa.provider.QueryExtractor; +import org.springframework.data.projection.ProjectionFactory; +import org.springframework.data.repository.core.RepositoryMetadata; + +/** + * @author Réda Housni Alaoui + */ +public interface JpaQueryMethodFactory { + + /** + * Creates a {@link JpaQueryMethod}. + * + * @param method must not be {@literal null} + * @param metadata must not be {@literal null} + * @param factory must not be {@literal null} + * @param extractor must not be {@literal null} + */ + JpaQueryMethod build(Method method, RepositoryMetadata metadata, ProjectionFactory factory, QueryExtractor extractor); + +} diff --git a/src/main/java/org/springframework/data/jpa/repository/support/JpaRepositoryFactory.java b/src/main/java/org/springframework/data/jpa/repository/support/JpaRepositoryFactory.java index a9535f2d5..a34d1893e 100644 --- a/src/main/java/org/springframework/data/jpa/repository/support/JpaRepositoryFactory.java +++ b/src/main/java/org/springframework/data/jpa/repository/support/JpaRepositoryFactory.java @@ -15,7 +15,7 @@ */ package org.springframework.data.jpa.repository.support; -import static org.springframework.data.querydsl.QuerydslUtils.*; +import static org.springframework.data.querydsl.QuerydslUtils.QUERY_DSL_PRESENT; import lombok.extern.slf4j.Slf4j; @@ -37,6 +37,7 @@ import org.springframework.data.jpa.repository.query.AbstractJpaQuery; import org.springframework.data.jpa.repository.query.EscapeCharacter; import org.springframework.data.jpa.repository.query.JpaQueryLookupStrategy; import org.springframework.data.jpa.repository.query.JpaQueryMethod; +import org.springframework.data.jpa.repository.query.JpaQueryMethodFactory; import org.springframework.data.jpa.util.JpaMetamodel; import org.springframework.data.projection.ProjectionFactory; import org.springframework.data.querydsl.EntityPathResolver; @@ -65,6 +66,7 @@ import org.springframework.util.ReflectionUtils; * @author Christoph Strobl * @author Jens Schauder * @author Stefan Fussenegger + * @author Réda Housni Alaoui */ public class JpaRepositoryFactory extends RepositoryFactorySupport { @@ -74,6 +76,7 @@ public class JpaRepositoryFactory extends RepositoryFactorySupport { private EntityPathResolver entityPathResolver; private EscapeCharacter escapeCharacter = EscapeCharacter.DEFAULT; + private JpaQueryMethodFactory queryMethodFactory; /** * Creates a new {@link JpaRepositoryFactory}. @@ -88,6 +91,7 @@ public class JpaRepositoryFactory extends RepositoryFactorySupport { this.extractor = PersistenceProvider.fromEntityManager(entityManager); this.crudMethodMetadataPostProcessor = new CrudMethodMetadataPostProcessor(); this.entityPathResolver = SimpleEntityPathResolver.INSTANCE; + this.queryMethodFactory = JpaQueryMethod.Factory.INSTANCE; addRepositoryProxyPostProcessor(crudMethodMetadataPostProcessor); addRepositoryProxyPostProcessor((factory, repositoryInformation) -> { @@ -134,6 +138,17 @@ public class JpaRepositoryFactory extends RepositoryFactorySupport { this.escapeCharacter = escapeCharacter; } + /** + * Configures the {@link JpaQueryMethodFactory} to be used. Defaults to {@link JpaQueryMethod.Factory#INSTANCE}. + * + * @param queryMethodFactory must not be {@literal null}. + */ + public void setQueryMethodFactory(JpaQueryMethodFactory queryMethodFactory) { + Assert.notNull(queryMethodFactory, "QueryMethodFactory must not be null!"); + + this.queryMethodFactory = queryMethodFactory; + } + /* * (non-Javadoc) * @see org.springframework.data.repository.core.support.RepositoryFactorySupport#getTargetRepository(org.springframework.data.repository.core.RepositoryMetadata) @@ -197,7 +212,8 @@ public class JpaRepositoryFactory extends RepositoryFactorySupport { protected Optional getQueryLookupStrategy(@Nullable Key key, QueryMethodEvaluationContextProvider evaluationContextProvider) { return Optional - .of(JpaQueryLookupStrategy.create(entityManager, key, extractor, evaluationContextProvider, escapeCharacter)); + .of( + JpaQueryLookupStrategy.create(entityManager, key, extractor, queryMethodFactory, evaluationContextProvider, escapeCharacter)); } /* diff --git a/src/main/java/org/springframework/data/jpa/repository/support/JpaRepositoryFactoryBean.java b/src/main/java/org/springframework/data/jpa/repository/support/JpaRepositoryFactoryBean.java index 3049be67a..5de800920 100644 --- a/src/main/java/org/springframework/data/jpa/repository/support/JpaRepositoryFactoryBean.java +++ b/src/main/java/org/springframework/data/jpa/repository/support/JpaRepositoryFactoryBean.java @@ -21,6 +21,8 @@ import javax.persistence.PersistenceContext; import org.springframework.beans.factory.ObjectProvider; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.jpa.repository.query.EscapeCharacter; +import org.springframework.data.jpa.repository.query.JpaQueryMethod; +import org.springframework.data.jpa.repository.query.JpaQueryMethodFactory; import org.springframework.data.mapping.context.MappingContext; import org.springframework.data.querydsl.EntityPathResolver; import org.springframework.data.querydsl.SimpleEntityPathResolver; @@ -38,6 +40,7 @@ import org.springframework.util.Assert; * @author Eberhard Wolff * @author Mark Paluch * @author Jens Schauder + * @author Réda Housni Alaoui * @param the type of the repository */ public class JpaRepositoryFactoryBean, S, ID> @@ -46,6 +49,7 @@ public class JpaRepositoryFactoryBean, S, ID> private @Nullable EntityManager entityManager; private EntityPathResolver entityPathResolver; private EscapeCharacter escapeCharacter = EscapeCharacter.DEFAULT; + private JpaQueryMethodFactory queryMethodFactory; /** * Creates a new {@link JpaRepositoryFactoryBean} for the given repository interface. @@ -86,6 +90,17 @@ public class JpaRepositoryFactoryBean, S, ID> this.entityPathResolver = resolver.getIfAvailable(() -> SimpleEntityPathResolver.INSTANCE); } + /** + * Configures the {@link JpaQueryMethodFactory} to be used. Will expect a canonical bean to be present but fallback to + * {@link JpaQueryMethod.Factory#INSTANCE} in case none is available. + * + * @param resolver must not be {@literal null}. + */ + @Autowired + public void setQueryMethodFactory(ObjectProvider resolver) { + this.queryMethodFactory = resolver.getIfAvailable(() -> JpaQueryMethod.Factory.INSTANCE); + } + /* * (non-Javadoc) * @see org.springframework.data.repository.core.support.TransactionalRepositoryFactoryBeanSupport#doCreateRepositoryFactory() @@ -106,6 +121,8 @@ public class JpaRepositoryFactoryBean, S, ID> JpaRepositoryFactory jpaRepositoryFactory = new JpaRepositoryFactory(entityManager); jpaRepositoryFactory.setEntityPathResolver(entityPathResolver); jpaRepositoryFactory.setEscapeCharacter(escapeCharacter); + jpaRepositoryFactory.setQueryMethodFactory(queryMethodFactory); + return jpaRepositoryFactory; } diff --git a/src/test/java/org/springframework/data/jpa/repository/query/CustomNonBindableJpaParametersTests.java b/src/test/java/org/springframework/data/jpa/repository/query/CustomNonBindableJpaParametersTests.java new file mode 100644 index 000000000..45636ab5f --- /dev/null +++ b/src/test/java/org/springframework/data/jpa/repository/query/CustomNonBindableJpaParametersTests.java @@ -0,0 +1,126 @@ +/* + * Copyright 2013-2019 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. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.data.jpa.repository.query; + +import static org.assertj.core.api.Assertions.assertThat; + +import java.lang.reflect.Method; +import java.util.Optional; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.ComponentScan; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.FilterType; +import org.springframework.context.annotation.ImportResource; +import org.springframework.core.MethodParameter; +import org.springframework.data.jpa.domain.sample.Product; +import org.springframework.data.jpa.provider.QueryExtractor; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.config.EnableJpaRepositories; +import org.springframework.data.projection.ProjectionFactory; +import org.springframework.data.repository.core.RepositoryMetadata; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +/** + * @author Réda Housni Alaoui + */ +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration +public class CustomNonBindableJpaParametersTests { + + @Autowired ProductRepository products; + + @Test + public void test() { + Product product = products.save(new Product()); + assertThat(products.findById(product.getId(), new NonBindable())).isNotEmpty(); + } + + private static class NonBindable { + + } + + public interface ProductRepository extends JpaRepository { + Optional findById(long id, NonBindable nonBindable); + } + + private static class NonBindableAwareJpaParameter extends JpaParameters.JpaParameter { + + private final MethodParameter parameter; + + NonBindableAwareJpaParameter(MethodParameter parameter) { + super(parameter); + this.parameter = parameter; + } + + @Override + public boolean isBindable() { + return !NonBindable.class.equals(parameter.getParameterType()) && super.isBindable(); + } + } + + private static class NonBindableAwareJpaParameters extends JpaParameters { + + public NonBindableAwareJpaParameters(Method method) { + super(method); + } + + @Override + protected JpaParameter createParameter(MethodParameter parameter) { + return new NonBindableAwareJpaParameter(parameter); + } + } + + private static class NonBindableAwareJpaQueryMethod extends JpaQueryMethod { + + NonBindableAwareJpaQueryMethod(Method method, RepositoryMetadata metadata, ProjectionFactory factory, + QueryExtractor extractor) { + super(method, metadata, factory, extractor); + } + + @Override + protected JpaParameters createParameters(Method method) { + return new NonBindableAwareJpaParameters(method); + } + } + + private static class NonBindableAwareJpaQueryMethodFactory implements JpaQueryMethodFactory { + + @Override + public JpaQueryMethod build(Method method, RepositoryMetadata metadata, ProjectionFactory factory, + QueryExtractor extractor) { + return new NonBindableAwareJpaQueryMethod(method, metadata, factory, extractor); + } + } + + @Configuration + @ImportResource("classpath:infrastructure.xml") + @EnableJpaRepositories(considerNestedRepositories = true, basePackageClasses = ProductRepository.class, // + includeFilters = @ComponentScan.Filter(value = { ProductRepository.class }, type = FilterType.ASSIGNABLE_TYPE)) + static class Config { + + @Bean + JpaQueryMethodFactory jpaQueryMethodFactory() { + return new NonBindableAwareJpaQueryMethodFactory(); + } + + } + +} diff --git a/src/test/java/org/springframework/data/jpa/repository/query/JpaQueryLookupStrategyUnitTests.java b/src/test/java/org/springframework/data/jpa/repository/query/JpaQueryLookupStrategyUnitTests.java index efff1b0a2..883d6be6e 100644 --- a/src/test/java/org/springframework/data/jpa/repository/query/JpaQueryLookupStrategyUnitTests.java +++ b/src/test/java/org/springframework/data/jpa/repository/query/JpaQueryLookupStrategyUnitTests.java @@ -15,9 +15,9 @@ */ package org.springframework.data.jpa.repository.query; -import static org.assertj.core.api.Assertions.*; -import static org.mockito.ArgumentMatchers.*; -import static org.mockito.Mockito.*; +import static org.assertj.core.api.Assertions.assertThatExceptionOfType; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.Mockito.when; import java.lang.reflect.Method; import java.util.List; @@ -50,11 +50,13 @@ import org.springframework.data.repository.query.QueryMethodEvaluationContextPro * @author Oliver Gierke * @author Thomas Darimont * @author Jens Schauder + * @author Réda Housni Alaoui */ @RunWith(MockitoJUnitRunner.class) public class JpaQueryLookupStrategyUnitTests { private static final QueryMethodEvaluationContextProvider EVALUATION_CONTEXT_PROVIDER = QueryMethodEvaluationContextProvider.DEFAULT; + private static final JpaQueryMethodFactory QUERY_METHOD_FACTORY = JpaQueryMethod.Factory.INSTANCE; @Mock EntityManager em; @Mock EntityManagerFactory emf; @@ -76,7 +78,7 @@ public class JpaQueryLookupStrategyUnitTests { public void invalidAnnotatedQueryCausesException() throws Exception { QueryLookupStrategy strategy = JpaQueryLookupStrategy.create(em, Key.CREATE_IF_NOT_FOUND, extractor, - EVALUATION_CONTEXT_PROVIDER, EscapeCharacter.DEFAULT); + QUERY_METHOD_FACTORY, EVALUATION_CONTEXT_PROVIDER, EscapeCharacter.DEFAULT); Method method = UserRepository.class.getMethod("findByFoo", String.class); RepositoryMetadata metadata = new DefaultRepositoryMetadata(UserRepository.class); @@ -92,7 +94,7 @@ public class JpaQueryLookupStrategyUnitTests { public void sholdThrowMorePreciseExceptionIfTryingToUsePaginationInNativeQueries() throws Exception { QueryLookupStrategy strategy = JpaQueryLookupStrategy.create(em, Key.CREATE_IF_NOT_FOUND, extractor, - EVALUATION_CONTEXT_PROVIDER, EscapeCharacter.DEFAULT); + QUERY_METHOD_FACTORY, EVALUATION_CONTEXT_PROVIDER, EscapeCharacter.DEFAULT); Method method = UserRepository.class.getMethod("findByInvalidNativeQuery", String.class, Sort.class); RepositoryMetadata metadata = new DefaultRepositoryMetadata(UserRepository.class);