DATAJPA-1497 - Polishing.
Improved naming and formatting. Made the `QueryExtractor` an argument of the `JpaQueryMethodFactory` constructor instead of its method. Original pull request: #305.
This commit is contained in:
@@ -81,7 +81,7 @@ public final class JpaQueryLookupStrategy {
|
||||
@Override
|
||||
public final RepositoryQuery resolveQuery(Method method, RepositoryMetadata metadata, ProjectionFactory factory,
|
||||
NamedQueries namedQueries) {
|
||||
return resolveQuery(queryMethodFactory.build(method, metadata, factory, provider), em, namedQueries);
|
||||
return resolveQuery(queryMethodFactory.build(method, metadata, factory), em, namedQueries);
|
||||
}
|
||||
|
||||
protected abstract RepositoryQuery resolveQuery(JpaQueryMethod method, EntityManager em, NamedQueries namedQueries);
|
||||
@@ -98,7 +98,8 @@ public final class JpaQueryLookupStrategy {
|
||||
private final PersistenceProvider persistenceProvider;
|
||||
private final EscapeCharacter escape;
|
||||
|
||||
public CreateQueryLookupStrategy(EntityManager em, QueryExtractor extractor, EscapeCharacter escape, JpaQueryMethodFactory queryMethodFactory) {
|
||||
public CreateQueryLookupStrategy(EntityManager em, QueryExtractor extractor, EscapeCharacter escape,
|
||||
JpaQueryMethodFactory queryMethodFactory) {
|
||||
|
||||
super(em, extractor, queryMethodFactory);
|
||||
this.persistenceProvider = PersistenceProvider.fromEntityManager(em);
|
||||
@@ -134,6 +135,7 @@ public final class JpaQueryLookupStrategy {
|
||||
JpaQueryMethodFactory queryMethodFactory, QueryMethodEvaluationContextProvider evaluationContextProvider) {
|
||||
|
||||
super(em, extractor, queryMethodFactory);
|
||||
|
||||
this.evaluationContextProvider = evaluationContextProvider;
|
||||
}
|
||||
|
||||
@@ -232,7 +234,8 @@ public final class JpaQueryLookupStrategy {
|
||||
* @return
|
||||
*/
|
||||
public static QueryLookupStrategy create(EntityManager em, @Nullable Key key, QueryExtractor extractor,
|
||||
JpaQueryMethodFactory queryMethodFactory, 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!");
|
||||
@@ -244,7 +247,7 @@ public final class JpaQueryLookupStrategy {
|
||||
case USE_DECLARED_QUERY:
|
||||
return new DeclaredQueryLookupStrategy(em, extractor, queryMethodFactory, evaluationContextProvider);
|
||||
case CREATE_IF_NOT_FOUND:
|
||||
return new CreateIfNotFoundQueryLookupStrategy(em, extractor,queryMethodFactory,
|
||||
return new CreateIfNotFoundQueryLookupStrategy(em, extractor, queryMethodFactory,
|
||||
new CreateQueryLookupStrategy(em, extractor, escape, queryMethodFactory),
|
||||
new DeclaredQueryLookupStrategy(em, extractor, queryMethodFactory, evaluationContextProvider));
|
||||
default:
|
||||
|
||||
@@ -90,6 +90,20 @@ public class JpaQueryMethod extends QueryMethod {
|
||||
private final Lazy<Boolean> isProcedureQuery;
|
||||
private final Lazy<JpaEntityMetadata<?>> entityMetadata;
|
||||
|
||||
/**
|
||||
* Creates a {@link JpaQueryMethodFactory} which will create instances of this class.
|
||||
*
|
||||
* @param extractor must not be {@literal null}.
|
||||
* @return a {@link JpaQueryMethodFactory} guaranteed to be not {@literal null}.
|
||||
* @since 2.3
|
||||
*/
|
||||
public static JpaQueryMethodFactory createMethodFactory(QueryExtractor extractor) {
|
||||
|
||||
Assert.notNull(extractor, "QueryExtractor must not be null");
|
||||
|
||||
return (method, metadata, factory) -> new JpaQueryMethod(method, metadata, factory, extractor);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a {@link JpaQueryMethod}.
|
||||
*
|
||||
@@ -427,19 +441,4 @@ 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,7 +22,12 @@ import org.springframework.data.projection.ProjectionFactory;
|
||||
import org.springframework.data.repository.core.RepositoryMetadata;
|
||||
|
||||
/**
|
||||
* A factory interface for creating {@link JpaQueryMethodFactory} instances.
|
||||
*
|
||||
* This may be implemented by extensions to Spring Data JPA in order create instances of custom subclasses.
|
||||
*
|
||||
* @author Réda Housni Alaoui
|
||||
* @since 2.3
|
||||
*/
|
||||
public interface JpaQueryMethodFactory {
|
||||
|
||||
@@ -32,8 +37,7 @@ public interface JpaQueryMethodFactory {
|
||||
* @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);
|
||||
JpaQueryMethod build(Method method, RepositoryMetadata metadata, ProjectionFactory factory);
|
||||
|
||||
}
|
||||
|
||||
@@ -91,7 +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;
|
||||
this.queryMethodFactory = JpaQueryMethod.createMethodFactory(extractor);
|
||||
|
||||
addRepositoryProxyPostProcessor(crudMethodMetadataPostProcessor);
|
||||
addRepositoryProxyPostProcessor((factory, repositoryInformation) -> {
|
||||
@@ -139,11 +139,12 @@ public class JpaRepositoryFactory extends RepositoryFactorySupport {
|
||||
}
|
||||
|
||||
/**
|
||||
* Configures the {@link JpaQueryMethodFactory} to be used. Defaults to {@link JpaQueryMethod.Factory#INSTANCE}.
|
||||
* Configures the {@link JpaQueryMethodFactory} to be used. Defaults to {@link JpaQueryMethod.DefaultJpaQueryMethodFactory#INSTANCE}.
|
||||
*
|
||||
* @param queryMethodFactory must not be {@literal null}.
|
||||
*/
|
||||
public void setQueryMethodFactory(JpaQueryMethodFactory queryMethodFactory) {
|
||||
|
||||
Assert.notNull(queryMethodFactory, "QueryMethodFactory must not be null!");
|
||||
|
||||
this.queryMethodFactory = queryMethodFactory;
|
||||
|
||||
@@ -20,6 +20,7 @@ import javax.persistence.PersistenceContext;
|
||||
|
||||
import org.springframework.beans.factory.ObjectProvider;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.jpa.provider.QueryExtractor;
|
||||
import org.springframework.data.jpa.repository.query.EscapeCharacter;
|
||||
import org.springframework.data.jpa.repository.query.JpaQueryMethod;
|
||||
import org.springframework.data.jpa.repository.query.JpaQueryMethodFactory;
|
||||
@@ -91,14 +92,14 @@ public class JpaRepositoryFactoryBean<T extends Repository<S, ID>, S, ID>
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
* Configures the {@link JpaQueryMethodFactory} to be used. Will expect a canonical bean to be present but will fallback to
|
||||
* {@link JpaQueryMethod#createMethodFactory(QueryExtractor)} in case none is available.
|
||||
*
|
||||
* @param resolver must not be {@literal null}.
|
||||
*/
|
||||
@Autowired
|
||||
public void setQueryMethodFactory(ObjectProvider<JpaQueryMethodFactory> resolver) {
|
||||
this.queryMethodFactory = resolver.getIfAvailable(() -> JpaQueryMethod.Factory.INSTANCE);
|
||||
this.queryMethodFactory = resolver.getIfAvailable(() -> null);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -121,7 +122,10 @@ public class JpaRepositoryFactoryBean<T extends Repository<S, ID>, S, ID>
|
||||
JpaRepositoryFactory jpaRepositoryFactory = new JpaRepositoryFactory(entityManager);
|
||||
jpaRepositoryFactory.setEntityPathResolver(entityPathResolver);
|
||||
jpaRepositoryFactory.setEscapeCharacter(escapeCharacter);
|
||||
jpaRepositoryFactory.setQueryMethodFactory(queryMethodFactory);
|
||||
|
||||
if (queryMethodFactory != null) {
|
||||
jpaRepositoryFactory.setQueryMethodFactory(queryMethodFactory);
|
||||
}
|
||||
|
||||
return jpaRepositoryFactory;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2013-2019 the original author or authors.
|
||||
* Copyright 2019-2020 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.
|
||||
@@ -15,7 +15,7 @@
|
||||
*/
|
||||
package org.springframework.data.jpa.repository.query;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.*;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Optional;
|
||||
@@ -30,6 +30,7 @@ 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.PersistenceProvider;
|
||||
import org.springframework.data.jpa.provider.QueryExtractor;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
|
||||
@@ -39,25 +40,28 @@ import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
|
||||
/**
|
||||
* Tests that the requirement of binding an argument to a query can get controlled by a module extending Spring Data
|
||||
* JPA.
|
||||
*
|
||||
* @author Réda Housni Alaoui
|
||||
*/
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@ContextConfiguration
|
||||
public class CustomNonBindableJpaParametersTests {
|
||||
public class CustomNonBindableJpaParametersIntegrationTests {
|
||||
|
||||
@Autowired ProductRepository products;
|
||||
|
||||
@Test
|
||||
public void test() {
|
||||
@Test // DATAJPA-1497
|
||||
public void methodWithNonBindableParameterCanBeCalled() {
|
||||
|
||||
Product product = products.save(new Product());
|
||||
|
||||
assertThat(products.findById(product.getId(), new NonBindable())).isNotEmpty();
|
||||
}
|
||||
|
||||
private static class NonBindable {
|
||||
private static class NonBindable {}
|
||||
|
||||
}
|
||||
|
||||
public interface ProductRepository extends JpaRepository<Product, Long> {
|
||||
interface ProductRepository extends JpaRepository<Product, Long> {
|
||||
Optional<Product> findById(long id, NonBindable nonBindable);
|
||||
}
|
||||
|
||||
@@ -103,9 +107,14 @@ public class CustomNonBindableJpaParametersTests {
|
||||
|
||||
private static class NonBindableAwareJpaQueryMethodFactory implements JpaQueryMethodFactory {
|
||||
|
||||
private final QueryExtractor extractor;
|
||||
|
||||
private NonBindableAwareJpaQueryMethodFactory(QueryExtractor extractor) {
|
||||
this.extractor = extractor;
|
||||
}
|
||||
|
||||
@Override
|
||||
public JpaQueryMethod build(Method method, RepositoryMetadata metadata, ProjectionFactory factory,
|
||||
QueryExtractor extractor) {
|
||||
public JpaQueryMethod build(Method method, RepositoryMetadata metadata, ProjectionFactory factory) {
|
||||
return new NonBindableAwareJpaQueryMethod(method, metadata, factory, extractor);
|
||||
}
|
||||
}
|
||||
@@ -118,9 +127,7 @@ public class CustomNonBindableJpaParametersTests {
|
||||
|
||||
@Bean
|
||||
JpaQueryMethodFactory jpaQueryMethodFactory() {
|
||||
return new NonBindableAwareJpaQueryMethodFactory();
|
||||
return new NonBindableAwareJpaQueryMethodFactory(PersistenceProvider.HIBERNATE);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -56,7 +56,6 @@ import org.springframework.data.repository.query.QueryMethodEvaluationContextPro
|
||||
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;
|
||||
@@ -65,6 +64,8 @@ public class JpaQueryLookupStrategyUnitTests {
|
||||
@Mock Metamodel metamodel;
|
||||
@Mock ProjectionFactory projectionFactory;
|
||||
|
||||
JpaQueryMethodFactory queryMethodFactory;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
|
||||
@@ -72,13 +73,14 @@ public class JpaQueryLookupStrategyUnitTests {
|
||||
when(em.getEntityManagerFactory()).thenReturn(emf);
|
||||
when(emf.createEntityManager()).thenReturn(em);
|
||||
when(em.getDelegate()).thenReturn(em);
|
||||
queryMethodFactory = JpaQueryMethod.createMethodFactory(extractor);
|
||||
}
|
||||
|
||||
@Test // DATAJPA-226
|
||||
public void invalidAnnotatedQueryCausesException() throws Exception {
|
||||
|
||||
QueryLookupStrategy strategy = JpaQueryLookupStrategy.create(em, Key.CREATE_IF_NOT_FOUND, extractor,
|
||||
QUERY_METHOD_FACTORY, EVALUATION_CONTEXT_PROVIDER, EscapeCharacter.DEFAULT);
|
||||
queryMethodFactory, EVALUATION_CONTEXT_PROVIDER, EscapeCharacter.DEFAULT);
|
||||
Method method = UserRepository.class.getMethod("findByFoo", String.class);
|
||||
RepositoryMetadata metadata = new DefaultRepositoryMetadata(UserRepository.class);
|
||||
|
||||
@@ -94,7 +96,7 @@ public class JpaQueryLookupStrategyUnitTests {
|
||||
public void sholdThrowMorePreciseExceptionIfTryingToUsePaginationInNativeQueries() throws Exception {
|
||||
|
||||
QueryLookupStrategy strategy = JpaQueryLookupStrategy.create(em, Key.CREATE_IF_NOT_FOUND, extractor,
|
||||
QUERY_METHOD_FACTORY, EVALUATION_CONTEXT_PROVIDER, EscapeCharacter.DEFAULT);
|
||||
queryMethodFactory, EVALUATION_CONTEXT_PROVIDER, EscapeCharacter.DEFAULT);
|
||||
Method method = UserRepository.class.getMethod("findByInvalidNativeQuery", String.class, Sort.class);
|
||||
RepositoryMetadata metadata = new DefaultRepositoryMetadata(UserRepository.class);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user