Polishing.
Migrate configuration setters for repository instances into JpaRepositoryConfigurationAware interface. Revert ProjectionFactory propagation through CrudMethodMetadata. Original pull request: #3432 See: #3410
This commit is contained in:
@@ -21,7 +21,6 @@ import java.lang.reflect.Method;
|
||||
import java.util.Optional;
|
||||
|
||||
import org.springframework.data.jpa.repository.EntityGraph;
|
||||
import org.springframework.data.projection.ProjectionFactory;
|
||||
import org.springframework.lang.Nullable;
|
||||
|
||||
/**
|
||||
@@ -87,10 +86,4 @@ public interface CrudMethodMetadata {
|
||||
*/
|
||||
Method getMethod();
|
||||
|
||||
/**
|
||||
* @return the {@link ProjectionFactory} to use or {@literal null} if not present.
|
||||
* @since ??
|
||||
*/
|
||||
@Nullable
|
||||
ProjectionFactory getProjectionFactory();
|
||||
}
|
||||
|
||||
@@ -25,10 +25,10 @@ import java.util.Set;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import org.aopalliance.intercept.MethodInterceptor;
|
||||
import org.aopalliance.intercept.MethodInvocation;
|
||||
|
||||
import org.springframework.aop.TargetSource;
|
||||
import org.springframework.aop.framework.ProxyFactory;
|
||||
import org.springframework.beans.factory.BeanClassLoaderAware;
|
||||
@@ -39,7 +39,6 @@ import org.springframework.data.jpa.repository.EntityGraph;
|
||||
import org.springframework.data.jpa.repository.Lock;
|
||||
import org.springframework.data.jpa.repository.Meta;
|
||||
import org.springframework.data.jpa.repository.QueryHints;
|
||||
import org.springframework.data.projection.ProjectionFactory;
|
||||
import org.springframework.data.repository.core.RepositoryInformation;
|
||||
import org.springframework.data.repository.core.support.RepositoryProxyPostProcessor;
|
||||
import org.springframework.lang.Nullable;
|
||||
@@ -63,11 +62,6 @@ import org.springframework.util.ReflectionUtils;
|
||||
class CrudMethodMetadataPostProcessor implements RepositoryProxyPostProcessor, BeanClassLoaderAware {
|
||||
|
||||
private @Nullable ClassLoader classLoader = ClassUtils.getDefaultClassLoader();
|
||||
private final Supplier<ProjectionFactory> projectionFactorySupplier;
|
||||
|
||||
CrudMethodMetadataPostProcessor(Supplier<ProjectionFactory> projectionFactorySupplier) {
|
||||
this.projectionFactorySupplier = projectionFactorySupplier;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBeanClassLoader(ClassLoader classLoader) {
|
||||
@@ -76,8 +70,7 @@ class CrudMethodMetadataPostProcessor implements RepositoryProxyPostProcessor, B
|
||||
|
||||
@Override
|
||||
public void postProcess(ProxyFactory factory, RepositoryInformation repositoryInformation) {
|
||||
factory
|
||||
.addAdvice(new CrudMethodMetadataPopulatingMethodInterceptor(repositoryInformation, projectionFactorySupplier));
|
||||
factory.addAdvice(new CrudMethodMetadataPopulatingMethodInterceptor(repositoryInformation));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -109,14 +102,11 @@ class CrudMethodMetadataPostProcessor implements RepositoryProxyPostProcessor, B
|
||||
|
||||
private final ConcurrentMap<Method, CrudMethodMetadata> metadataCache = new ConcurrentHashMap<>();
|
||||
private final Set<Method> implementations = new HashSet<>();
|
||||
private final Supplier<ProjectionFactory> projectionFactory;
|
||||
|
||||
CrudMethodMetadataPopulatingMethodInterceptor(RepositoryInformation repositoryInformation,
|
||||
Supplier<ProjectionFactory> projectionFactory) {
|
||||
CrudMethodMetadataPopulatingMethodInterceptor(RepositoryInformation repositoryInformation) {
|
||||
|
||||
ReflectionUtils.doWithMethods(repositoryInformation.getRepositoryInterface(), implementations::add,
|
||||
method -> !repositoryInformation.isQueryMethod(method));
|
||||
this.projectionFactory = projectionFactory;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -161,7 +151,7 @@ class CrudMethodMetadataPostProcessor implements RepositoryProxyPostProcessor, B
|
||||
|
||||
if (methodMetadata == null) {
|
||||
|
||||
methodMetadata = new DefaultCrudMethodMetadata(method, projectionFactory.get());
|
||||
methodMetadata = new DefaultCrudMethodMetadata(method);
|
||||
CrudMethodMetadata tmp = metadataCache.putIfAbsent(method, methodMetadata);
|
||||
|
||||
if (tmp != null) {
|
||||
@@ -196,17 +186,15 @@ class CrudMethodMetadataPostProcessor implements RepositoryProxyPostProcessor, B
|
||||
private final @Nullable String comment;
|
||||
private final Optional<EntityGraph> entityGraph;
|
||||
private final Method method;
|
||||
private ProjectionFactory projectionFactory;
|
||||
|
||||
/**
|
||||
* Creates a new {@link DefaultCrudMethodMetadata} for the given {@link Method}.
|
||||
*
|
||||
* @param method must not be {@literal null}.
|
||||
*/
|
||||
DefaultCrudMethodMetadata(Method method, ProjectionFactory projectionFactory) {
|
||||
DefaultCrudMethodMetadata(Method method) {
|
||||
|
||||
Assert.notNull(method, "Method must not be null");
|
||||
this.projectionFactory = projectionFactory;
|
||||
|
||||
this.lockModeType = findLockModeType(method);
|
||||
this.queryHints = findQueryHints(method, it -> true);
|
||||
@@ -288,10 +276,6 @@ class CrudMethodMetadataPostProcessor implements RepositoryProxyPostProcessor, B
|
||||
return method;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ProjectionFactory getProjectionFactory() {
|
||||
return projectionFactory;
|
||||
}
|
||||
}
|
||||
|
||||
private static class ThreadBoundTargetSource implements TargetSource {
|
||||
|
||||
@@ -96,8 +96,7 @@ class FetchableFluentQueryByPredicate<S, R> extends FluentQuerySupport<S, R> imp
|
||||
Assert.notNull(sort, "Sort must not be null");
|
||||
|
||||
return new FetchableFluentQueryByPredicate<>(predicate, entityType, resultType, this.sort.and(sort), limit,
|
||||
properties, finder, scroll, pagedFinder, countOperation, existsOperation, entityManager,
|
||||
getProjectionFactory());
|
||||
properties, finder, scroll, pagedFinder, countOperation, existsOperation, entityManager, projectionFactory);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -106,7 +105,7 @@ class FetchableFluentQueryByPredicate<S, R> extends FluentQuerySupport<S, R> imp
|
||||
Assert.isTrue(limit >= 0, "Limit must not be negative");
|
||||
|
||||
return new FetchableFluentQueryByPredicate<>(predicate, entityType, resultType, sort, limit, properties, finder,
|
||||
scroll, pagedFinder, countOperation, existsOperation, entityManager, getProjectionFactory());
|
||||
scroll, pagedFinder, countOperation, existsOperation, entityManager, projectionFactory);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -119,7 +118,7 @@ class FetchableFluentQueryByPredicate<S, R> extends FluentQuerySupport<S, R> imp
|
||||
}
|
||||
|
||||
return new FetchableFluentQueryByPredicate<>(predicate, entityType, resultType, sort, limit, properties, finder,
|
||||
scroll, pagedFinder, countOperation, existsOperation, entityManager, getProjectionFactory());
|
||||
scroll, pagedFinder, countOperation, existsOperation, entityManager, projectionFactory);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -127,7 +126,7 @@ class FetchableFluentQueryByPredicate<S, R> extends FluentQuerySupport<S, R> imp
|
||||
|
||||
return new FetchableFluentQueryByPredicate<>(predicate, entityType, resultType, sort, limit,
|
||||
mergeProperties(properties), finder, scroll, pagedFinder, countOperation, existsOperation, entityManager,
|
||||
getProjectionFactory());
|
||||
projectionFactory);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -90,7 +90,7 @@ class FetchableFluentQueryBySpecification<S, R> extends FluentQuerySupport<S, R>
|
||||
Assert.notNull(sort, "Sort must not be null");
|
||||
|
||||
return new FetchableFluentQueryBySpecification<>(spec, entityType, resultType, this.sort.and(sort), limit,
|
||||
properties, finder, scroll, countOperation, existsOperation, entityManager, getProjectionFactory());
|
||||
properties, finder, scroll, countOperation, existsOperation, entityManager, projectionFactory);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -99,7 +99,7 @@ class FetchableFluentQueryBySpecification<S, R> extends FluentQuerySupport<S, R>
|
||||
Assert.isTrue(limit >= 0, "Limit must not be negative");
|
||||
|
||||
return new FetchableFluentQueryBySpecification<>(spec, entityType, resultType, this.sort.and(sort), limit,
|
||||
properties, finder, scroll, countOperation, existsOperation, entityManager, getProjectionFactory());
|
||||
properties, finder, scroll, countOperation, existsOperation, entityManager, projectionFactory);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -111,14 +111,14 @@ class FetchableFluentQueryBySpecification<S, R> extends FluentQuerySupport<S, R>
|
||||
}
|
||||
|
||||
return new FetchableFluentQueryBySpecification<>(spec, entityType, resultType, sort, limit, properties, finder,
|
||||
scroll, countOperation, existsOperation, entityManager, getProjectionFactory());
|
||||
scroll, countOperation, existsOperation, entityManager, projectionFactory);
|
||||
}
|
||||
|
||||
@Override
|
||||
public FetchableFluentQuery<R> project(Collection<String> properties) {
|
||||
|
||||
return new FetchableFluentQueryBySpecification<>(spec, entityType, resultType, sort, limit, properties, finder,
|
||||
scroll, countOperation, existsOperation, entityManager, getProjectionFactory());
|
||||
scroll, countOperation, existsOperation, entityManager, projectionFactory);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -27,7 +27,6 @@ import org.springframework.core.convert.support.DefaultConversionService;
|
||||
import org.springframework.data.domain.ScrollPosition;
|
||||
import org.springframework.data.domain.Sort;
|
||||
import org.springframework.data.projection.ProjectionFactory;
|
||||
import org.springframework.data.projection.SpelAwareProxyProjectionFactory;
|
||||
import org.springframework.lang.Nullable;
|
||||
|
||||
/**
|
||||
@@ -47,8 +46,7 @@ abstract class FluentQuerySupport<S, R> {
|
||||
protected final int limit;
|
||||
protected final Set<String> properties;
|
||||
protected final Class<S> entityType;
|
||||
|
||||
private final ProjectionFactory projectionFactory;
|
||||
protected final ProjectionFactory projectionFactory;
|
||||
|
||||
FluentQuerySupport(Class<R> resultType, Sort sort, int limit, @Nullable Collection<String> properties,
|
||||
Class<S> entityType, ProjectionFactory projectionFactory) {
|
||||
@@ -67,10 +65,6 @@ abstract class FluentQuerySupport<S, R> {
|
||||
this.projectionFactory = projectionFactory;
|
||||
}
|
||||
|
||||
ProjectionFactory getProjectionFactory() {
|
||||
return projectionFactory;
|
||||
}
|
||||
|
||||
final Collection<String> mergeProperties(Collection<String> additionalProperties) {
|
||||
|
||||
Set<String> newProperties = new HashSet<>();
|
||||
|
||||
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
* Copyright 2024 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.support;
|
||||
|
||||
import org.springframework.data.jpa.repository.query.EscapeCharacter;
|
||||
import org.springframework.data.projection.ProjectionFactory;
|
||||
|
||||
/**
|
||||
* Interface to be implemented by classes that want to be aware of their configuration in a JPA repository context.
|
||||
*
|
||||
* @author Mark Paluch
|
||||
* @since 3.3
|
||||
*/
|
||||
public interface JpaRepositoryConfigurationAware {
|
||||
|
||||
/**
|
||||
* Configures the {@link EscapeCharacter} to be used with the repository.
|
||||
*
|
||||
* @param escapeCharacter must not be {@literal null}.
|
||||
*/
|
||||
default void setEscapeCharacter(EscapeCharacter escapeCharacter) {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Configures the {@link ProjectionFactory} to be used with the repository.
|
||||
*
|
||||
* @param projectionFactory must not be {@literal null}.
|
||||
*/
|
||||
default void setProjectionFactory(ProjectionFactory projectionFactory) {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Configures the {@link CrudMethodMetadata} to be used with the repository.
|
||||
*
|
||||
* @param metadata must not be {@literal null}.
|
||||
*/
|
||||
default void setRepositoryMethodMetadata(CrudMethodMetadata metadata) {
|
||||
|
||||
}
|
||||
}
|
||||
@@ -83,6 +83,7 @@ public class JpaRepositoryFactory extends RepositoryFactorySupport {
|
||||
private final EntityManager entityManager;
|
||||
private final QueryExtractor extractor;
|
||||
private final CrudMethodMetadataPostProcessor crudMethodMetadataPostProcessor;
|
||||
private final CrudMethodMetadata crudMethodMetadata;
|
||||
|
||||
private EntityPathResolver entityPathResolver;
|
||||
private EscapeCharacter escapeCharacter = EscapeCharacter.DEFAULT;
|
||||
@@ -100,7 +101,7 @@ public class JpaRepositoryFactory extends RepositoryFactorySupport {
|
||||
|
||||
this.entityManager = entityManager;
|
||||
this.extractor = PersistenceProvider.fromEntityManager(entityManager);
|
||||
this.crudMethodMetadataPostProcessor = new CrudMethodMetadataPostProcessor(() -> getProjectionFactory());
|
||||
this.crudMethodMetadataPostProcessor = new CrudMethodMetadataPostProcessor();
|
||||
this.entityPathResolver = SimpleEntityPathResolver.INSTANCE;
|
||||
this.queryMethodFactory = new DefaultJpaQueryMethodFactory(extractor);
|
||||
this.queryRewriterProvider = QueryRewriterProvider.simple();
|
||||
@@ -116,6 +117,8 @@ public class JpaRepositoryFactory extends RepositoryFactorySupport {
|
||||
if (extractor.equals(PersistenceProvider.ECLIPSELINK)) {
|
||||
addQueryCreationListener(new EclipseLinkProjectionQueryCreationListener(entityManager));
|
||||
}
|
||||
|
||||
this.crudMethodMetadata = crudMethodMetadataPostProcessor.getCrudMethodMetadata();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -192,8 +195,8 @@ public class JpaRepositoryFactory extends RepositoryFactorySupport {
|
||||
protected final JpaRepositoryImplementation<?, ?> getTargetRepository(RepositoryInformation information) {
|
||||
|
||||
JpaRepositoryImplementation<?, ?> repository = getTargetRepository(information, entityManager);
|
||||
repository.setRepositoryMethodMetadata(crudMethodMetadataPostProcessor.getCrudMethodMetadata());
|
||||
repository.setEscapeCharacter(escapeCharacter);
|
||||
|
||||
invokeAwareMethods(repository);
|
||||
|
||||
return repository;
|
||||
}
|
||||
@@ -249,8 +252,7 @@ public class JpaRepositoryFactory extends RepositoryFactorySupport {
|
||||
@Override
|
||||
protected RepositoryFragments getRepositoryFragments(RepositoryMetadata metadata) {
|
||||
|
||||
return getRepositoryFragments(metadata, entityManager, entityPathResolver,
|
||||
crudMethodMetadataPostProcessor.getCrudMethodMetadata());
|
||||
return getRepositoryFragments(metadata, entityManager, entityPathResolver, this.crudMethodMetadata);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -279,13 +281,23 @@ public class JpaRepositoryFactory extends RepositoryFactorySupport {
|
||||
"Cannot combine Querydsl and reactive repository support in a single interface");
|
||||
}
|
||||
|
||||
return RepositoryFragments.just(new QuerydslJpaPredicateExecutor<>(getEntityInformation(metadata.getDomainType()),
|
||||
entityManager, resolver, crudMethodMetadata));
|
||||
QuerydslJpaPredicateExecutor<?> querydslJpaPredicateExecutor = new QuerydslJpaPredicateExecutor<>(
|
||||
getEntityInformation(metadata.getDomainType()), entityManager, resolver, crudMethodMetadata);
|
||||
invokeAwareMethods(querydslJpaPredicateExecutor);
|
||||
|
||||
return RepositoryFragments.just(querydslJpaPredicateExecutor);
|
||||
}
|
||||
|
||||
return RepositoryFragments.empty();
|
||||
}
|
||||
|
||||
private void invokeAwareMethods(JpaRepositoryConfigurationAware repository) {
|
||||
|
||||
repository.setRepositoryMethodMetadata(crudMethodMetadata);
|
||||
repository.setEscapeCharacter(escapeCharacter);
|
||||
repository.setProjectionFactory(getProjectionFactory());
|
||||
}
|
||||
|
||||
private static boolean isTransactionNeeded(Class<?> repositoryClass) {
|
||||
|
||||
Method[] methods = ReflectionUtils.getAllDeclaredMethods(repositoryClass);
|
||||
|
||||
@@ -17,7 +17,6 @@ package org.springframework.data.jpa.repository.support;
|
||||
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
|
||||
import org.springframework.data.jpa.repository.query.EscapeCharacter;
|
||||
import org.springframework.data.repository.NoRepositoryBean;
|
||||
|
||||
/**
|
||||
@@ -28,21 +27,7 @@ import org.springframework.data.repository.NoRepositoryBean;
|
||||
* @author Jens Schauder
|
||||
*/
|
||||
@NoRepositoryBean
|
||||
public interface JpaRepositoryImplementation<T, ID> extends JpaRepository<T, ID>, JpaSpecificationExecutor<T> {
|
||||
public interface JpaRepositoryImplementation<T, ID>
|
||||
extends JpaRepository<T, ID>, JpaSpecificationExecutor<T>, JpaRepositoryConfigurationAware {
|
||||
|
||||
/**
|
||||
* Configures the {@link CrudMethodMetadata} to be used with the repository.
|
||||
*
|
||||
* @param crudMethodMetadata must not be {@literal null}.
|
||||
*/
|
||||
void setRepositoryMethodMetadata(CrudMethodMetadata crudMethodMetadata);
|
||||
|
||||
/**
|
||||
* Configures the {@link EscapeCharacter} to be used with the repository.
|
||||
*
|
||||
* @param escapeCharacter Must not be {@literal null}.
|
||||
*/
|
||||
default void setEscapeCharacter(EscapeCharacter escapeCharacter) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -41,7 +41,6 @@ import org.springframework.data.projection.SpelAwareProxyProjectionFactory;
|
||||
import org.springframework.data.querydsl.EntityPathResolver;
|
||||
import org.springframework.data.querydsl.QSort;
|
||||
import org.springframework.data.querydsl.QuerydslPredicateExecutor;
|
||||
import org.springframework.data.repository.core.RepositoryMetadata;
|
||||
import org.springframework.data.repository.query.FluentQuery.FetchableFluentQuery;
|
||||
import org.springframework.data.support.PageableExecutionUtils;
|
||||
import org.springframework.lang.Nullable;
|
||||
@@ -74,14 +73,15 @@ import com.querydsl.jpa.impl.AbstractJPAQuery;
|
||||
* @author Greg Turnquist
|
||||
* @author Yanming Zhou
|
||||
*/
|
||||
public class QuerydslJpaPredicateExecutor<T> implements QuerydslPredicateExecutor<T> {
|
||||
public class QuerydslJpaPredicateExecutor<T> implements QuerydslPredicateExecutor<T>, JpaRepositoryConfigurationAware {
|
||||
|
||||
private final JpaEntityInformation<T, ?> entityInformation;
|
||||
private final EntityPath<T> path;
|
||||
private final Querydsl querydsl;
|
||||
private final QuerydslQueryStrategy scrollQueryAdapter;
|
||||
private final EntityManager entityManager;
|
||||
private final CrudMethodMetadata metadata;
|
||||
private @Nullable CrudMethodMetadata metadata;
|
||||
private @Nullable ProjectionFactory projectionFactory;
|
||||
|
||||
/**
|
||||
* Creates a new {@link QuerydslJpaPredicateExecutor} from the given domain class and {@link EntityManager} and uses
|
||||
@@ -103,6 +103,16 @@ public class QuerydslJpaPredicateExecutor<T> implements QuerydslPredicateExecuto
|
||||
this.scrollQueryAdapter = new QuerydslQueryStrategy();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setRepositoryMethodMetadata(CrudMethodMetadata metadata) {
|
||||
this.metadata = metadata;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setProjectionFactory(ProjectionFactory projectionFactory) {
|
||||
this.projectionFactory = projectionFactory;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<T> findOne(Predicate predicate) {
|
||||
|
||||
@@ -199,7 +209,7 @@ public class QuerydslJpaPredicateExecutor<T> implements QuerydslPredicateExecuto
|
||||
select = (AbstractJPAQuery<?, ?>) querydsl.applySorting(sort, select);
|
||||
|
||||
if (scrollPosition instanceof OffsetScrollPosition offset) {
|
||||
if(!offset.isInitial()) {
|
||||
if (!offset.isInitial()) {
|
||||
select.offset(offset.getOffset() + 1);
|
||||
}
|
||||
}
|
||||
@@ -227,8 +237,7 @@ public class QuerydslJpaPredicateExecutor<T> implements QuerydslPredicateExecuto
|
||||
this::count, //
|
||||
this::exists, //
|
||||
entityManager, //
|
||||
getProjectionFactory()
|
||||
);
|
||||
getProjectionFactory());
|
||||
|
||||
return queryFunction.apply((FetchableFluentQuery<S>) fluentQuery);
|
||||
}
|
||||
@@ -336,12 +345,11 @@ public class QuerydslJpaPredicateExecutor<T> implements QuerydslPredicateExecuto
|
||||
|
||||
private ProjectionFactory getProjectionFactory() {
|
||||
|
||||
CrudMethodMetadata metadata = getRepositoryMethodMetadata();
|
||||
if(metadata == null || metadata.getProjectionFactory() == null) {
|
||||
return new SpelAwareProxyProjectionFactory();
|
||||
if (projectionFactory == null) {
|
||||
projectionFactory = new SpelAwareProxyProjectionFactory();
|
||||
}
|
||||
|
||||
return metadata.getProjectionFactory();
|
||||
return projectionFactory;
|
||||
}
|
||||
|
||||
class QuerydslQueryStrategy implements QueryStrategy<Expression<?>, BooleanExpression> {
|
||||
|
||||
@@ -105,6 +105,7 @@ public class SimpleJpaRepository<T, ID> implements JpaRepositoryImplementation<T
|
||||
private final PersistenceProvider provider;
|
||||
|
||||
private @Nullable CrudMethodMetadata metadata;
|
||||
private @Nullable ProjectionFactory projectionFactory;
|
||||
private EscapeCharacter escapeCharacter = EscapeCharacter.DEFAULT;
|
||||
|
||||
/**
|
||||
@@ -137,11 +138,11 @@ public class SimpleJpaRepository<T, ID> implements JpaRepositoryImplementation<T
|
||||
* Configures a custom {@link CrudMethodMetadata} to be used to detect {@link LockModeType}s and query hints to be
|
||||
* applied to queries.
|
||||
*
|
||||
* @param crudMethodMetadata
|
||||
* @param metadata
|
||||
*/
|
||||
@Override
|
||||
public void setRepositoryMethodMetadata(CrudMethodMetadata crudMethodMetadata) {
|
||||
this.metadata = crudMethodMetadata;
|
||||
public void setRepositoryMethodMetadata(CrudMethodMetadata metadata) {
|
||||
this.metadata = metadata;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -149,6 +150,11 @@ public class SimpleJpaRepository<T, ID> implements JpaRepositoryImplementation<T
|
||||
this.escapeCharacter = escapeCharacter;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setProjectionFactory(ProjectionFactory projectionFactory) {
|
||||
this.projectionFactory = projectionFactory;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
protected CrudMethodMetadata getRepositoryMethodMetadata() {
|
||||
return metadata;
|
||||
@@ -907,12 +913,11 @@ public class SimpleJpaRepository<T, ID> implements JpaRepositoryImplementation<T
|
||||
|
||||
private ProjectionFactory getProjectionFactory() {
|
||||
|
||||
CrudMethodMetadata metadata = getRepositoryMethodMetadata();
|
||||
if(metadata == null || metadata.getProjectionFactory() == null) {
|
||||
return new SpelAwareProxyProjectionFactory();
|
||||
if (projectionFactory == null) {
|
||||
projectionFactory = new SpelAwareProxyProjectionFactory();
|
||||
}
|
||||
|
||||
return metadata.getProjectionFactory();
|
||||
return projectionFactory;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -18,10 +18,10 @@ package org.springframework.data.jpa.repository.support;
|
||||
import static org.assertj.core.api.Assertions.*;
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
import jakarta.persistence.LockModeType;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
import org.aopalliance.intercept.MethodInterceptor;
|
||||
import org.aopalliance.intercept.MethodInvocation;
|
||||
import org.junit.jupiter.api.Test;
|
||||
@@ -34,7 +34,6 @@ import org.mockito.quality.Strictness;
|
||||
import org.springframework.aop.framework.ProxyFactory;
|
||||
import org.springframework.data.jpa.repository.Lock;
|
||||
import org.springframework.data.jpa.repository.support.CrudMethodMetadataPostProcessor.CrudMethodMetadataPopulatingMethodInterceptor;
|
||||
import org.springframework.data.projection.SpelAwareProxyProjectionFactory;
|
||||
import org.springframework.data.repository.core.RepositoryInformation;
|
||||
import org.springframework.transaction.support.TransactionSynchronizationManager;
|
||||
|
||||
@@ -57,7 +56,7 @@ class CrudMethodMetadataPopulatingMethodInterceptorUnitTests {
|
||||
|
||||
ProxyFactory factory = new ProxyFactory(new Object());
|
||||
factory.addInterface(Sample.class);
|
||||
factory.addAdvice(new CrudMethodMetadataPopulatingMethodInterceptor(information, SpelAwareProxyProjectionFactory::new));
|
||||
factory.addAdvice(new CrudMethodMetadataPopulatingMethodInterceptor(information));
|
||||
factory.addAdvice(new MethodInterceptor() {
|
||||
|
||||
@Override
|
||||
@@ -79,7 +78,7 @@ class CrudMethodMetadataPopulatingMethodInterceptorUnitTests {
|
||||
when(information.getRepositoryInterface()).thenReturn((Class) Sample.class);
|
||||
|
||||
CrudMethodMetadataPopulatingMethodInterceptor interceptor = new CrudMethodMetadataPopulatingMethodInterceptor(
|
||||
information, () -> new SpelAwareProxyProjectionFactory());
|
||||
information);
|
||||
interceptor.invoke(invocation);
|
||||
|
||||
assertThat(TransactionSynchronizationManager.getResource(method)).isNull();
|
||||
@@ -89,7 +88,7 @@ class CrudMethodMetadataPopulatingMethodInterceptorUnitTests {
|
||||
@SuppressWarnings("unchecked")
|
||||
void looksUpCrudMethodMetadataForEveryInvocation() {
|
||||
|
||||
CrudMethodMetadata metadata = new CrudMethodMetadataPostProcessor(() -> new SpelAwareProxyProjectionFactory()).getCrudMethodMetadata();
|
||||
CrudMethodMetadata metadata = new CrudMethodMetadataPostProcessor().getCrudMethodMetadata();
|
||||
when(information.isQueryMethod(any())).thenReturn(false);
|
||||
when(information.getRepositoryInterface()).thenReturn((Class) Sample.class);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user