diff --git a/pom.xml b/pom.xml index f518c186f5..ff741d5be9 100644 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ org.springframework.data spring-data-mongodb-parent - 4.4.0-SNAPSHOT + 4.4.x-GH-4744-SNAPSHOT pom Spring Data MongoDB diff --git a/spring-data-mongodb-benchmarks/pom.xml b/spring-data-mongodb-benchmarks/pom.xml index a3dc49f892..973dbb4522 100644 --- a/spring-data-mongodb-benchmarks/pom.xml +++ b/spring-data-mongodb-benchmarks/pom.xml @@ -7,7 +7,7 @@ org.springframework.data spring-data-mongodb-parent - 4.4.0-SNAPSHOT + 4.4.x-GH-4744-SNAPSHOT ../pom.xml diff --git a/spring-data-mongodb-distribution/pom.xml b/spring-data-mongodb-distribution/pom.xml index e33930bfd2..3a275dc0ab 100644 --- a/spring-data-mongodb-distribution/pom.xml +++ b/spring-data-mongodb-distribution/pom.xml @@ -15,7 +15,7 @@ org.springframework.data spring-data-mongodb-parent - 4.4.0-SNAPSHOT + 4.4.x-GH-4744-SNAPSHOT ../pom.xml diff --git a/spring-data-mongodb/pom.xml b/spring-data-mongodb/pom.xml index fafe9c8793..939d481f5e 100644 --- a/spring-data-mongodb/pom.xml +++ b/spring-data-mongodb/pom.xml @@ -13,7 +13,7 @@ org.springframework.data spring-data-mongodb-parent - 4.4.0-SNAPSHOT + 4.4.x-GH-4744-SNAPSHOT ../pom.xml diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/aot/LazyLoadingProxyAotProcessor.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/aot/LazyLoadingProxyAotProcessor.java index 09080c32d5..530ffce510 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/aot/LazyLoadingProxyAotProcessor.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/aot/LazyLoadingProxyAotProcessor.java @@ -24,7 +24,6 @@ import java.util.Set; import org.springframework.aot.generate.GenerationContext; -import org.springframework.aot.hint.MemberCategory; import org.springframework.aot.hint.TypeReference; import org.springframework.core.annotation.AnnotatedElementUtils; import org.springframework.core.annotation.MergedAnnotations; @@ -77,8 +76,7 @@ public void registerLazyLoadingProxyIfNeeded(Class type, GenerationContext ge LazyLoadingInterceptor::none); // see: spring-projects/spring-framework/issues/29309 - generationContext.getRuntimeHints().reflection().registerType(proxyClass, - MemberCategory.INVOKE_DECLARED_CONSTRUCTORS, MemberCategory.INVOKE_DECLARED_METHODS, MemberCategory.DECLARED_FIELDS); + generationContext.getRuntimeHints().reflection().registerType(proxyClass, MongoAotReflectionHelper::cglibProxyReflectionMemberAccess); } }); } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/aot/MongoAotReflectionHelper.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/aot/MongoAotReflectionHelper.java new file mode 100644 index 0000000000..e3d3a30336 --- /dev/null +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/aot/MongoAotReflectionHelper.java @@ -0,0 +1,31 @@ +/* + * 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.mongodb.aot; + +import org.springframework.aot.hint.MemberCategory; +import org.springframework.aot.hint.TypeHint.Builder; + +/** + * @author Christoph Strobl + */ +public final class MongoAotReflectionHelper { + + public static void cglibProxyReflectionMemberAccess(Builder builder) { + + builder.withMembers(MemberCategory.INVOKE_DECLARED_CONSTRUCTORS, MemberCategory.INVOKE_DECLARED_METHODS, + MemberCategory.DECLARED_FIELDS); + } +} diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/BasicQuery.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/BasicQuery.java index b381a21593..79ceeda95e 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/BasicQuery.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/BasicQuery.java @@ -85,6 +85,20 @@ public BasicQuery(Document queryObject, Document fieldsObject) { this.sortObject = new Document(); } + /** + * Create a BasicQuery given a {@link Query}. The resulting query is a copy of {@link Query}. + * + * @param query + */ + public BasicQuery(Query query) { + + super(query); + this.queryObject = query.getQueryObject(); + this.setFieldsObject(query.getFieldsObject()); + this.setSortObject(query.getSortObject()); + this.setMeta(query.getMeta()); + } + @Override public Query addCriteria(CriteriaDefinition criteria) { diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/Query.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/Query.java index 2b307f15c7..d79b22aef7 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/Query.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/Query.java @@ -79,6 +79,20 @@ public class Query implements ReadConcernAware, ReadPreferenceAware { private Optional collation = Optional.empty(); + Query(Query query) { + this.restrictedTypes = query.restrictedTypes; + this.fieldSpec = query.fieldSpec; + this.sort = query.sort; + this.limit = query.limit; + this.skip = query.skip; + this.keysetScrollPosition = query.keysetScrollPosition; + this.readConcern = query.readConcern; + this.readPreference = query.readPreference; + this.hint = query.hint; + this.meta = query.meta; + this.collation = query.collation; + } + /** * Static factory method to create a {@link Query} using the provided {@link CriteriaDefinition}. * diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/aot/RepositoryRuntimeHints.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/aot/RepositoryRuntimeHints.java index 203e5e9810..46e6c9044c 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/aot/RepositoryRuntimeHints.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/aot/RepositoryRuntimeHints.java @@ -92,4 +92,5 @@ private static void registerQuerydslHints(RuntimeHints hints, @Nullable ClassLoa private static boolean isAopPresent(@Nullable ClassLoader classLoader) { return ClassUtils.isPresent("org.springframework.aop.Pointcut", classLoader); } + } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/AbstractMongoQuery.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/AbstractMongoQuery.java index 52eef58340..61bfa0f7b3 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/AbstractMongoQuery.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/AbstractMongoQuery.java @@ -20,6 +20,7 @@ import org.bson.Document; import org.bson.codecs.configuration.CodecRegistry; + import org.springframework.data.mapping.model.SpELExpressionEvaluator; import org.springframework.data.mongodb.core.ExecutableFindOperation.ExecutableFind; import org.springframework.data.mongodb.core.ExecutableFindOperation.FindWithQuery; @@ -155,7 +156,7 @@ protected Object doExecute(MongoQueryMethod method, ResultProcessor processor, C * @since 4.2 */ private Query applyAnnotatedReadPreferenceIfPresent(Query query) { - + if (!method.hasAnnotatedReadPreference()) { return query; } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/QueryUtils.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/QueryUtils.java index 1aab34055a..c6ad7a634f 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/QueryUtils.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/QueryUtils.java @@ -18,9 +18,11 @@ import java.util.Arrays; import java.util.List; -import org.aopalliance.intercept.MethodInterceptor; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; import org.bson.Document; -import org.springframework.aop.framework.ProxyFactory; + +import org.springframework.data.mongodb.core.query.BasicQuery; import org.springframework.data.mongodb.core.query.Collation; import org.springframework.data.mongodb.core.query.Query; import org.springframework.data.repository.query.QueryMethodEvaluationContextProvider; @@ -39,6 +41,8 @@ */ class QueryUtils { + protected static final Log LOGGER = LogFactory.getLog(QueryUtils.class); + /** * Decorate {@link Query} and add a default sort expression to the given {@link Query}. Attributes of the given * {@code sort} may be overwritten by the sort explicitly defined by the {@link Query} itself. @@ -53,20 +57,13 @@ static Query decorateSort(Query query, Document defaultSort) { return query; } - ProxyFactory factory = new ProxyFactory(query); - factory.addAdvice((MethodInterceptor) invocation -> { + BasicQuery defaultSortQuery = query instanceof BasicQuery bq ? bq : new BasicQuery(query); - if (!invocation.getMethod().getName().equals("getSortObject")) { - return invocation.proceed(); - } + Document combinedSort = new Document(defaultSort); + combinedSort.putAll(defaultSortQuery.getSortObject()); + defaultSortQuery.setSortObject(combinedSort); - Document combinedSort = new Document(defaultSort); - combinedSort.putAll((Document) invocation.proceed()); - return combinedSort; - }); - factory.setInterfaces(new Class[0]); - - return (Query) factory.getProxy(query.getClass().getClassLoader()); + return defaultSortQuery; } /** @@ -111,17 +108,18 @@ static int indexOfAssignableParameter(Class type, Class[] parameters) { */ static int indexOfAssignableParameter(Class type, List> parameters) { - if(parameters.isEmpty()) { + if (parameters.isEmpty()) { return -1; } int i = 0; - for(Class parameterType : parameters) { - if(ClassUtils.isAssignable(type, parameterType)) { + for (Class parameterType : parameters) { + if (ClassUtils.isAssignable(type, parameterType)) { return i; } i++; } return -1; } + }