Browse Source

Polishing.

Reformat code. Use existing SimpleTypeHolder instead of static MongoSimpleTypes.

See: #5027
Original pull request: #5038
pull/5040/head
Mark Paluch 4 months ago
parent
commit
46ece81d00
No known key found for this signature in database
GPG Key ID: 55BC6374BAA9D973
  1. 80
      spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoTemplate.java
  2. 2
      spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/QueryOperations.java
  3. 37
      spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/aot/AggregationBlocks.java
  4. 3
      spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/aot/AotPlaceholders.java
  5. 33
      spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/aot/AotQueryCreator.java
  6. 10
      spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/aot/AotStringQuery.java
  7. 1
      spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/aot/MongoAotRepositoryFragmentSupport.java
  8. 9
      spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/aot/MongoCodeBlocks.java
  9. 31
      spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/aot/MongoRepositoryContributor.java
  10. 1
      spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/aot/Snippet.java
  11. 2
      spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/MongoQueryCreator.java
  12. 42
      spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/AggregationTests.java

80
spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoTemplate.java

@ -111,11 +111,9 @@ import org.springframework.data.mongodb.core.query.UpdateDefinition.ArrayFilter; @@ -111,11 +111,9 @@ import org.springframework.data.mongodb.core.query.UpdateDefinition.ArrayFilter;
import org.springframework.data.mongodb.core.timeseries.Granularity;
import org.springframework.data.mongodb.core.validation.Validator;
import org.springframework.data.projection.EntityProjection;
import org.springframework.data.projection.ProjectionFactory;
import org.springframework.data.util.CloseableIterator;
import org.springframework.data.util.Lazy;
import org.springframework.data.util.Optionals;
import org.springframework.data.util.TypeInformation;
import org.springframework.lang.Contract;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
@ -498,7 +496,7 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware, @@ -498,7 +496,7 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware,
return doStream(query, entityType, collectionName, returnType, QueryResultConverter.entity());
}
@SuppressWarnings({"ConstantConditions", "NullAway"})
@SuppressWarnings({ "ConstantConditions", "NullAway" })
<T, R> Stream<R> doStream(Query query, Class<?> entityType, String collectionName, Class<T> returnType,
QueryResultConverter<? super T, ? extends R> resultConverter) {
@ -523,8 +521,7 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware, @@ -523,8 +521,7 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware,
DocumentCallback<R> resultReader = getResultReader(projection, collectionName, resultConverter);
return new CloseableIterableCursorAdapter<>(cursor, exceptionTranslator,
resultReader).stream();
return new CloseableIterableCursorAdapter<>(cursor, exceptionTranslator, resultReader).stream();
});
}
@ -1152,7 +1149,7 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware, @@ -1152,7 +1149,7 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware,
@Override
public <T> @Nullable T findAndModify(Query query, UpdateDefinition update, FindAndModifyOptions options,
Class<T> entityClass, String collectionName) {
Class<T> entityClass, String collectionName) {
return findAndModify(query, update, options, entityClass, collectionName, QueryResultConverter.entity());
}
@ -1182,12 +1179,13 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware, @@ -1182,12 +1179,13 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware,
@Override
public <S, T> @Nullable T findAndReplace(Query query, S replacement, FindAndReplaceOptions options,
Class<S> entityType, String collectionName, Class<T> resultType) {
return findAndReplace(query, replacement, options, entityType, collectionName, resultType, QueryResultConverter.entity());
Class<S> entityType, String collectionName, Class<T> resultType) {
return findAndReplace(query, replacement, options, entityType, collectionName, resultType,
QueryResultConverter.entity());
}
<S, T, R> @Nullable R findAndReplace(Query query, S replacement, FindAndReplaceOptions options,
Class<S> entityType, String collectionName, Class<T> resultType, QueryResultConverter<? super T, ? extends R> resultConverter) {
<S, T, R> @Nullable R findAndReplace(Query query, S replacement, FindAndReplaceOptions options, Class<S> entityType,
String collectionName, Class<T> resultType, QueryResultConverter<? super T, ? extends R> resultConverter) {
Assert.notNull(query, "Query must not be null");
Assert.notNull(replacement, "Replacement must not be null");
@ -1215,7 +1213,8 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware, @@ -1215,7 +1213,8 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware,
maybeCallBeforeSave(replacement, mappedReplacement, collectionName);
R saved = doFindAndReplace(collectionPreparer, collectionName, mappedQuery, mappedFields, mappedSort,
queryContext.getCollation(entityType).orElse(null), entityType, mappedReplacement, options, projection, resultConverter);
queryContext.getCollation(entityType).orElse(null), entityType, mappedReplacement, options, projection,
resultConverter);
if (saved != null) {
maybeEmitEvent(new AfterSaveEvent<>(saved, mappedReplacement, collectionName));
@ -1508,7 +1507,7 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware, @@ -1508,7 +1507,7 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware,
initialized = maybeCallBeforeSave(initialized, document, collectionName);
MappedDocument mappedDocument = queryOperations.createInsertContext(MappedDocument.of(document))
.prepareId(uninitialized.getClass());
.prepareId(uninitialized.getClass());
documentList.add(mappedDocument.getDocument());
initializedBatchToSave.add(initialized);
@ -2221,14 +2220,14 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware, @@ -2221,14 +2220,14 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware,
}
};
List<T> result = doFind(collectionName, createDelegate(query), query.getQueryObject(), query.getFieldsObject(), entityClass,
new QueryCursorPreparer(query, entityClass), callback);
List<T> result = doFind(collectionName, createDelegate(query), query.getQueryObject(), query.getFieldsObject(),
entityClass, new QueryCursorPreparer(query, entityClass), callback);
if (!CollectionUtils.isEmpty(result)) {
Criteria[] criterias = ids.stream() //
.map(it -> Criteria.where("_id").is(it)) //
.toArray(Criteria[]::new);
.map(it -> Criteria.where("_id").is(it)) //
.toArray(Criteria[]::new);
Query removeQuery = new Query(criterias.length == 1 ? criterias[0] : new Criteria().orOperator(criterias));
if (query.hasReadPreference()) {
@ -2270,20 +2269,19 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware, @@ -2270,20 +2269,19 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware,
return doAggregate(aggregation, collectionName, outputType, QueryResultConverter.entity(), context);
}
@SuppressWarnings({"ConstantConditions", "NullAway"})
@SuppressWarnings({ "ConstantConditions", "NullAway" })
<T, O> AggregationResults<O> doAggregate(Aggregation aggregation, String collectionName, Class<T> outputType,
QueryResultConverter<? super T, ? extends O> resultConverter, AggregationOperationContext context) {
final DocumentCallback<O> callback;
if(aggregation instanceof TypedAggregation<?> ta && outputType.isInterface()) {
if (aggregation instanceof TypedAggregation<?> ta && outputType.isInterface()) {
EntityProjection<T, ?> projection = operations.introspectProjection(outputType, ta.getInputType());
ProjectingReadCallback cb = new ProjectingReadCallback(mongoConverter, projection, collectionName);
callback = new QueryResultConverterCallback<>(resultConverter,
cb);
callback = new QueryResultConverterCallback<>(resultConverter, cb);
} else {
callback = new QueryResultConverterCallback<>(resultConverter,
new ReadDocumentCallback<>(mongoConverter, outputType, collectionName));
new ReadDocumentCallback<>(mongoConverter, outputType, collectionName));
}
AggregationOptions options = aggregation.getOptions();
@ -2370,8 +2368,7 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware, @@ -2370,8 +2368,7 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware,
@SuppressWarnings({ "ConstantConditions", "NullAway" })
<T, O> Stream<O> doAggregateStream(Aggregation aggregation, String collectionName, Class<T> outputType,
QueryResultConverter<? super T, ? extends O> resultConverter,
@Nullable AggregationOperationContext context) {
QueryResultConverter<? super T, ? extends O> resultConverter, @Nullable AggregationOperationContext context) {
Assert.notNull(aggregation, "Aggregation pipeline must not be null");
Assert.hasText(collectionName, "Collection name must not be null or empty");
@ -2649,9 +2646,8 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware, @@ -2649,9 +2646,8 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware,
* @return the converted object or {@literal null} if none exists.
*/
@Nullable
protected <T> T doFindOne(String collectionName,
CollectionPreparer<MongoCollection<Document>> collectionPreparer, Document query, Document fields,
Class<T> entityClass) {
protected <T> T doFindOne(String collectionName, CollectionPreparer<MongoCollection<Document>> collectionPreparer,
Document query, Document fields, Class<T> entityClass) {
return doFindOne(collectionName, collectionPreparer, query, fields, CursorPreparer.NO_OP_PREPARER, entityClass);
}
@ -2670,9 +2666,8 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware, @@ -2670,9 +2666,8 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware,
*/
@Nullable
@SuppressWarnings("ConstantConditions")
protected <T> T doFindOne(String collectionName,
CollectionPreparer<MongoCollection<Document>> collectionPreparer, Document query, Document fields,
CursorPreparer preparer, Class<T> entityClass) {
protected <T> T doFindOne(String collectionName, CollectionPreparer<MongoCollection<Document>> collectionPreparer,
Document query, Document fields, CursorPreparer preparer, Class<T> entityClass) {
MongoPersistentEntity<?> entity = mappingContext.getPersistentEntity(entityClass);
@ -2870,9 +2865,9 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware, @@ -2870,9 +2865,9 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware,
@SuppressWarnings("ConstantConditions")
<S, T> @Nullable T doFindAndModify(CollectionPreparer<MongoCollection<Document>> collectionPreparer,
String collectionName,
Document query, @Nullable Document fields, @Nullable Document sort, Class<S> entityClass, UpdateDefinition update,
@Nullable FindAndModifyOptions options, QueryResultConverter<? super S, ? extends T> resultConverter) {
String collectionName, Document query, @Nullable Document fields, @Nullable Document sort, Class<S> entityClass,
UpdateDefinition update, @Nullable FindAndModifyOptions options,
QueryResultConverter<? super S, ? extends T> resultConverter) {
if (options == null) {
options = new FindAndModifyOptions();
@ -2894,7 +2889,8 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware, @@ -2894,7 +2889,8 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware,
serializeToJsonSafely(mappedUpdate), collectionName));
}
DocumentCallback<T> callback = getResultReader(EntityProjection.nonProjecting(entityClass), collectionName, resultConverter);
DocumentCallback<T> callback = getResultReader(EntityProjection.nonProjecting(entityClass), collectionName,
resultConverter);
return executeFindOneInternal(
new FindAndModifyCallback(collectionPreparer, mappedQuery, fields, sort, mappedUpdate,
@ -2919,8 +2915,7 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware, @@ -2919,8 +2915,7 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware,
*/
@Nullable
protected <S, T> T doFindAndReplace(CollectionPreparer<MongoCollection<Document>> collectionPreparer,
String collectionName,
Document mappedQuery, Document mappedFields, Document mappedSort,
String collectionName, Document mappedQuery, Document mappedFields, Document mappedSort,
com.mongodb.client.model.@Nullable Collation collation, Class<S> entityType, Document replacement,
FindAndReplaceOptions options, Class<T> resultType) {
@ -2963,10 +2958,10 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware, @@ -2963,10 +2958,10 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware,
*/
@Nullable
private <S, T, R> R doFindAndReplace(CollectionPreparer<MongoCollection<Document>> collectionPreparer,
String collectionName,
Document mappedQuery, Document mappedFields, Document mappedSort,
String collectionName, Document mappedQuery, Document mappedFields, Document mappedSort,
com.mongodb.client.model.@Nullable Collation collation, Class<T> entityType, Document replacement,
FindAndReplaceOptions options, EntityProjection<S, T> projection, QueryResultConverter<? super S, ? extends R> resultConverter) {
FindAndReplaceOptions options, EntityProjection<S, T> projection,
QueryResultConverter<? super S, ? extends R> resultConverter) {
if (LOGGER.isDebugEnabled()) {
LOGGER
@ -2979,8 +2974,7 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware, @@ -2979,8 +2974,7 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware,
DocumentCallback<R> callback = getResultReader(projection, collectionName, resultConverter);
return executeFindOneInternal(new FindAndReplaceCallback(collectionPreparer, mappedQuery, mappedFields, mappedSort,
replacement, collation, options),callback,
collectionName);
replacement, collation, options), callback, collectionName);
}
@SuppressWarnings("NullAway")
@ -3158,8 +3152,8 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware, @@ -3158,8 +3152,8 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware,
return getMappedSortObject(sortObject, mappingContext.getPersistentEntity(type));
}
private @Nullable Document getMappedSortObject(@Nullable Document sortObject, @Nullable MongoPersistentEntity<?> entity) {
private @Nullable Document getMappedSortObject(@Nullable Document sortObject,
@Nullable MongoPersistentEntity<?> entity) {
if (ObjectUtils.isEmpty(sortObject)) {
return null;
@ -3392,7 +3386,7 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware, @@ -3392,7 +3386,7 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware,
private final Document fields;
private final Document sort;
private final Document update;
private final com.mongodb.client.model.@Nullable Collation collation;
private final com.mongodb.client.model.@Nullable Collation collation;
private final FindAndReplaceOptions options;
FindAndReplaceCallback(CollectionPreparer<MongoCollection<Document>> collectionPreparer, Document query,

2
spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/QueryOperations.java

@ -377,7 +377,7 @@ class QueryOperations { @@ -377,7 +377,7 @@ class QueryOperations {
mappedFields = queryMapper.getMappedFields(fields, entity);
} else {
mappedFields = propertyOperations.computeMappedFieldsForProjection(projection, fields);
if(projection.getMappedType().getType().isInterface()) {
if (projection.getMappedType().getType().isInterface()) {
mappedFields = queryMapper.getMappedFields(mappedFields, entity);
}
mappedFields = queryMapper.addMetaAttributes(mappedFields, entity);

37
spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/aot/AggregationBlocks.java

@ -22,10 +22,12 @@ import java.util.stream.Stream; @@ -22,10 +22,12 @@ import java.util.stream.Stream;
import org.bson.Document;
import org.jspecify.annotations.NullUnmarked;
import org.springframework.core.ResolvableType;
import org.springframework.core.annotation.MergedAnnotation;
import org.springframework.data.domain.SliceImpl;
import org.springframework.data.domain.Sort.Order;
import org.springframework.data.mapping.model.SimpleTypeHolder;
import org.springframework.data.mongodb.core.MongoOperations;
import org.springframework.data.mongodb.core.aggregation.Aggregation;
import org.springframework.data.mongodb.core.aggregation.AggregationOperation;
@ -33,7 +35,6 @@ import org.springframework.data.mongodb.core.aggregation.AggregationOptions; @@ -33,7 +35,6 @@ import org.springframework.data.mongodb.core.aggregation.AggregationOptions;
import org.springframework.data.mongodb.core.aggregation.AggregationPipeline;
import org.springframework.data.mongodb.core.aggregation.AggregationResults;
import org.springframework.data.mongodb.core.aggregation.TypedAggregation;
import org.springframework.data.mongodb.core.mapping.MongoSimpleTypes;
import org.springframework.data.mongodb.core.query.Collation;
import org.springframework.data.mongodb.repository.Hint;
import org.springframework.data.mongodb.repository.ReadPreference;
@ -58,12 +59,15 @@ class AggregationBlocks { @@ -58,12 +59,15 @@ class AggregationBlocks {
static class AggregationExecutionCodeBlockBuilder {
private final AotQueryMethodGenerationContext context;
private final SimpleTypeHolder simpleTypeHolder;
private final MongoQueryMethod queryMethod;
private String aggregationVariableName;
AggregationExecutionCodeBlockBuilder(AotQueryMethodGenerationContext context, MongoQueryMethod queryMethod) {
AggregationExecutionCodeBlockBuilder(AotQueryMethodGenerationContext context, SimpleTypeHolder simpleTypeHolder,
MongoQueryMethod queryMethod) {
this.context = context;
this.simpleTypeHolder = simpleTypeHolder;
this.queryMethod = queryMethod;
}
@ -80,7 +84,7 @@ class AggregationBlocks { @@ -80,7 +84,7 @@ class AggregationBlocks {
builder.add("\n");
Class<?> outputType = getOutputType(queryMethod);
Class<?> outputType = getOutputType(simpleTypeHolder, queryMethod);
if (ReflectionUtils.isVoid(queryMethod.getReturnedObjectType())) {
builder.addStatement("$L.aggregate($L, $T.class)", mongoOpsRef, aggregationVariableName, outputType);
@ -152,13 +156,19 @@ class AggregationBlocks { @@ -152,13 +156,19 @@ class AggregationBlocks {
}
private static Class<?> getOutputType(MongoQueryMethod queryMethod) {
private static Class<?> getOutputType(SimpleTypeHolder simpleTypeHolder, MongoQueryMethod queryMethod) {
Class<?> outputType = queryMethod.getReturnedObjectType();
if (MongoSimpleTypes.HOLDER.isSimpleType(outputType)) {
outputType = Document.class;
} else if (ClassUtils.isAssignable(AggregationResults.class, outputType) && queryMethod.getReturnType().getComponentType() != null) {
outputType = queryMethod.getReturnType().getComponentType().getType();
if (simpleTypeHolder.isSimpleType(outputType)) {
return Document.class;
}
if (ClassUtils.isAssignable(AggregationResults.class, outputType)
&& queryMethod.getReturnType().getComponentType() != null) {
return queryMethod.getReturnType().getComponentType().getType();
}
return outputType;
}
@ -166,6 +176,7 @@ class AggregationBlocks { @@ -166,6 +176,7 @@ class AggregationBlocks {
static class AggregationCodeBlockBuilder {
private final AotQueryMethodGenerationContext context;
private final SimpleTypeHolder simpleTypeHolder;
private final MongoQueryMethod queryMethod;
private final String parameterNames;
@ -174,9 +185,11 @@ class AggregationBlocks { @@ -174,9 +185,11 @@ class AggregationBlocks {
private String aggregationVariableName;
private boolean pipelineOnly;
AggregationCodeBlockBuilder(AotQueryMethodGenerationContext context, MongoQueryMethod queryMethod) {
AggregationCodeBlockBuilder(AotQueryMethodGenerationContext context, SimpleTypeHolder simpleTypeHolder,
MongoQueryMethod queryMethod) {
this.context = context;
this.simpleTypeHolder = simpleTypeHolder;
this.queryMethod = queryMethod;
this.parameterNames = StringUtils.collectionToDelimitedString(context.getAllParameterNames(), ", ");
}
@ -230,7 +243,7 @@ class AggregationBlocks { @@ -230,7 +243,7 @@ class AggregationBlocks {
builder.add(aggregationStages(context.localVariable("stages"), source.stages()));
if (StringUtils.hasText(sortParameter)) {
Class<?> outputType = getOutputType(queryMethod);
Class<?> outputType = getOutputType(simpleTypeHolder, queryMethod);
builder.add(sortingStage(sortParameter, outputType));
}
@ -324,7 +337,7 @@ class AggregationBlocks { @@ -324,7 +337,7 @@ class AggregationBlocks {
context.localVariable("sortDocument"), context.localVariable("order"));
builder.endControlFlow();
if (outputType == Document.class || MongoSimpleTypes.HOLDER.isSimpleType(outputType)
if (outputType == Document.class || simpleTypeHolder.isSimpleType(outputType)
|| ClassUtils.isAssignable(context.getRepositoryInformation().getDomainType(), outputType)) {
builder.addStatement("$L.add(new $T($S, $L))", context.localVariable("stages"), Document.class, "$sort",
context.localVariable("sortDocument"));
@ -343,7 +356,7 @@ class AggregationBlocks { @@ -343,7 +356,7 @@ class AggregationBlocks {
Builder builder = CodeBlock.builder();
builder.add(sortingStage(pageableProvider + ".getSort()", getOutputType(queryMethod)));
builder.add(sortingStage(pageableProvider + ".getSort()", getOutputType(simpleTypeHolder, queryMethod)));
builder.beginControlFlow("if ($L.isPaged())", pageableProvider);
builder.beginControlFlow("if ($L.getOffset() > 0)", pageableProvider);

3
spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/aot/AotPlaceholders.java

@ -279,7 +279,8 @@ class AotPlaceholders { @@ -279,7 +279,8 @@ class AotPlaceholders {
this.options = options;
}
@Nullable String regexOptions() {
@Nullable
String regexOptions() {
return options;
}

33
spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/aot/AotQueryCreator.java

@ -68,13 +68,7 @@ import com.mongodb.DBRef; @@ -68,13 +68,7 @@ import com.mongodb.DBRef;
* @author Christoph Strobl
* @since 5.0
*/
class AotQueryCreator {
private final MappingContext<?, MongoPersistentProperty> mappingContext;
public AotQueryCreator(MappingContext<?, MongoPersistentProperty> mappingContext) {
this.mappingContext = mappingContext;
}
record AotQueryCreator(MappingContext<?, MongoPersistentProperty> mappingContext) {
@SuppressWarnings("NullAway")
AotStringQuery createQuery(PartTree partTree, QueryMethod queryMethod, Method source) {
@ -129,7 +123,7 @@ class AotQueryCreator { @@ -129,7 +123,7 @@ class AotQueryCreator {
return criteria.is(param);
}
if(part.getType().equals(Type.NOT_LIKE)) {
if (part.getType().equals(Type.NOT_LIKE)) {
return criteria.raw("$not", param);
}
@ -179,15 +173,16 @@ class AotQueryCreator { @@ -179,15 +173,16 @@ class AotQueryCreator {
private final List<Object> placeholders;
@Nullable Part getPartForIndex(PartTree partTree, Parameter parameter) {
if(!parameter.isBindable()) {
@Nullable
Part getPartForIndex(PartTree partTree, Parameter parameter) {
if (!parameter.isBindable()) {
return null;
}
List<Part> parts = partTree.getParts().stream().toList();
int counter = 0;
int counter = 0;
for (Part part : parts) {
if(counter == parameter.getIndex()) {
if (counter == parameter.getIndex()) {
return part;
}
counter += part.getNumberOfArguments();
@ -196,17 +191,14 @@ class AotQueryCreator { @@ -196,17 +191,14 @@ class AotQueryCreator {
}
public PlaceholderParameterAccessor(PartTree partTree, QueryMethod queryMethod) {
if (queryMethod.getParameters().getNumberOfParameters() == 0) {
placeholders = List.of();
} else {
placeholders = new ArrayList<>();
Parameters<?, ?> parameters = queryMethod.getParameters();
for (Parameter parameter : parameters.toList()) {
if (ClassUtils.isAssignable(GeoJson.class, parameter.getType())) {
placeholders.add(parameter.getIndex(), AotPlaceholders.geoJson(parameter.getIndex(), ""));
@ -224,8 +216,15 @@ class AotQueryCreator { @@ -224,8 +216,15 @@ class AotQueryCreator {
placeholders.add(parameter.getIndex(), AotPlaceholders.regex(parameter.getIndex(), null));
} else {
Part partForIndex = getPartForIndex(partTree, parameter);
if(partForIndex != null && (partForIndex.getType().equals(Type.LIKE) || partForIndex.getType().equals(Type.NOT_LIKE))) {
placeholders.add(parameter.getIndex(), AotPlaceholders.regex(parameter.getIndex(), partForIndex.shouldIgnoreCase().equals(IgnoreCaseType.ALWAYS) || partForIndex.shouldIgnoreCase().equals(IgnoreCaseType.WHEN_POSSIBLE) ? "i": null));
if (partForIndex != null
&& (partForIndex.getType().equals(Type.LIKE) || partForIndex.getType().equals(Type.NOT_LIKE))) {
placeholders
.add(parameter.getIndex(),
AotPlaceholders
.regex(parameter.getIndex(),
partForIndex.shouldIgnoreCase().equals(IgnoreCaseType.ALWAYS)
|| partForIndex.shouldIgnoreCase().equals(IgnoreCaseType.WHEN_POSSIBLE) ? "i"
: null));
} else {
placeholders.add(parameter.getIndex(), AotPlaceholders.indexed(parameter.getIndex()));
}

10
spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/aot/AotStringQuery.java

@ -28,7 +28,6 @@ import org.springframework.data.mongodb.core.query.Collation; @@ -28,7 +28,6 @@ import org.springframework.data.mongodb.core.query.Collation;
import org.springframework.data.mongodb.core.query.Field;
import org.springframework.data.mongodb.core.query.Meta;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.repository.aot.AotPlaceholders.Placeholder;
import org.springframework.data.mongodb.repository.aot.AotPlaceholders.RegexPlaceholder;
import org.springframework.util.StringUtils;
@ -80,19 +79,20 @@ class AotStringQuery extends Query { @@ -80,19 +79,20 @@ class AotStringQuery extends Query {
}
boolean isRegexPlaceholderAt(int index) {
if(this.placeholders.isEmpty()) {
if (this.placeholders.isEmpty()) {
return false;
}
return this.placeholders.get(index) instanceof RegexPlaceholder;
}
@Nullable String getRegexOptions(int index) {
if(this.placeholders.isEmpty()) {
@Nullable
String getRegexOptions(int index) {
if (this.placeholders.isEmpty()) {
return null;
}
return this.placeholders.get(index) instanceof RegexPlaceholder rgp ? rgp.regexOptions() : null;
return this.placeholders.get(index) instanceof RegexPlaceholder rgp ? rgp.regexOptions() : null;
}
@Override

1
spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/aot/MongoAotRepositoryFragmentSupport.java

@ -189,7 +189,6 @@ public class MongoAotRepositoryFragmentSupport { @@ -189,7 +189,6 @@ public class MongoAotRepositoryFragmentSupport {
criteria.lt(value);
}
}
};
}

9
spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/aot/MongoCodeBlocks.java

@ -20,6 +20,7 @@ import java.util.regex.Pattern; @@ -20,6 +20,7 @@ import java.util.regex.Pattern;
import org.bson.Document;
import org.jspecify.annotations.Nullable;
import org.springframework.core.annotation.MergedAnnotation;
import org.springframework.data.mapping.model.SimpleTypeHolder;
import org.springframework.data.mongodb.repository.ReadPreference;
import org.springframework.data.mongodb.repository.aot.AggregationBlocks.AggregationCodeBlockBuilder;
import org.springframework.data.mongodb.repository.aot.AggregationBlocks.AggregationExecutionCodeBlockBuilder;
@ -118,24 +119,28 @@ class MongoCodeBlocks { @@ -118,24 +119,28 @@ class MongoCodeBlocks {
* Builder for generating aggregation (pipeline) parsing {@link CodeBlock}.
*
* @param context
* @param simpleTypeHolder
* @param queryMethod
* @return
*/
static AggregationCodeBlockBuilder aggregationBlockBuilder(AotQueryMethodGenerationContext context,
SimpleTypeHolder simpleTypeHolder,
MongoQueryMethod queryMethod) {
return new AggregationCodeBlockBuilder(context, queryMethod);
return new AggregationCodeBlockBuilder(context, simpleTypeHolder, queryMethod);
}
/**
* Builder for generating aggregation execution {@link CodeBlock}.
*
* @param context
* @param simpleTypeHolder
* @param queryMethod
* @return
*/
static AggregationExecutionCodeBlockBuilder aggregationExecutionBlockBuilder(AotQueryMethodGenerationContext context,
SimpleTypeHolder simpleTypeHolder,
MongoQueryMethod queryMethod) {
return new AggregationExecutionCodeBlockBuilder(context, queryMethod);
return new AggregationExecutionCodeBlockBuilder(context, simpleTypeHolder, queryMethod);
}
/**

31
spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/aot/MongoRepositoryContributor.java

@ -28,6 +28,7 @@ import org.jspecify.annotations.Nullable; @@ -28,6 +28,7 @@ import org.jspecify.annotations.Nullable;
import org.springframework.core.annotation.AnnotatedElementUtils;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.data.mapping.model.SimpleTypeHolder;
import org.springframework.data.mongodb.core.MongoOperations;
import org.springframework.data.mongodb.core.aggregation.AggregationUpdate;
import org.springframework.data.mongodb.core.convert.MongoCustomConversions;
@ -68,6 +69,7 @@ public class MongoRepositoryContributor extends RepositoryContributor { @@ -68,6 +69,7 @@ public class MongoRepositoryContributor extends RepositoryContributor {
private static final Log logger = LogFactory.getLog(MongoRepositoryContributor.class);
private final AotQueryCreator queryCreator;
private final SimpleTypeHolder simpleTypeHolder;
private final MongoMappingContext mappingContext;
private final NamedQueries namedQueries;
@ -85,8 +87,10 @@ public class MongoRepositoryContributor extends RepositoryContributor { @@ -85,8 +87,10 @@ public class MongoRepositoryContributor extends RepositoryContributor {
MongoCustomConversions mongoCustomConversions = MongoCustomConversions
.create(MongoCustomConversions.MongoConverterConfigurationAdapter::useNativeDriverJavaTimeCodecs);
this.simpleTypeHolder = mongoCustomConversions.getSimpleTypeHolder();
this.mappingContext = new MongoMappingContext();
this.mappingContext.setSimpleTypeHolder(mongoCustomConversions.getSimpleTypeHolder());
this.mappingContext.setSimpleTypeHolder(this.simpleTypeHolder);
this.mappingContext.setAutoIndexCreation(false);
this.mappingContext.afterPropertiesSet();
@ -150,7 +154,7 @@ public class MongoRepositoryContributor extends RepositoryContributor { @@ -150,7 +154,7 @@ public class MongoRepositoryContributor extends RepositoryContributor {
if (queryMethod.hasAnnotatedAggregation()) {
AggregationInteraction aggregation = new AggregationInteraction(queryMethod.getAnnotatedAggregation());
queryMetadata = aggregation;
contribution = aggregationMethodContributor(queryMethod, aggregation);
contribution = aggregationMethodContributor(queryMethod, simpleTypeHolder, aggregation);
} else {
QueryInteraction query = createStringQuery(getRepositoryInformation(), queryMethod,
@ -193,7 +197,7 @@ public class MongoRepositoryContributor extends RepositoryContributor { @@ -193,7 +197,7 @@ public class MongoRepositoryContributor extends RepositoryContributor {
if (!ObjectUtils.isEmpty(updateSource.pipeline())) {
AggregationUpdateInteraction update = new AggregationUpdateInteraction(query, updateSource.pipeline());
queryMetadata = update;
contribution = aggregationUpdateMethodContributor(queryMethod, update);
contribution = aggregationUpdateMethodContributor(queryMethod, simpleTypeHolder, update);
}
}
} else {
@ -210,17 +214,7 @@ public class MongoRepositoryContributor extends RepositoryContributor { @@ -210,17 +214,7 @@ public class MongoRepositoryContributor extends RepositoryContributor {
return MethodContributor.forQueryMethod(queryMethod).metadataOnly(queryMetadata);
}
MethodContributor.RepositoryMethodContribution finalContribution = contribution;
return MethodContributor.forQueryMethod(queryMethod).withMetadata(queryMetadata).contribute(context -> {
CodeBlock.Builder builder = CodeBlock.builder();
// builder.addStatement("class ExpressionMarker{}");
builder.add(finalContribution.contribute(context));
return builder.build();
});
return MethodContributor.forQueryMethod(queryMethod).withMetadata(queryMetadata).contribute(contribution);
}
@SuppressWarnings("NullAway")
@ -289,6 +283,7 @@ public class MongoRepositoryContributor extends RepositoryContributor { @@ -289,6 +283,7 @@ public class MongoRepositoryContributor extends RepositoryContributor {
}
static MethodContributor.RepositoryMethodContribution aggregationMethodContributor(MongoQueryMethod queryMethod,
SimpleTypeHolder simpleTypeHolder,
AggregationInteraction aggregation) {
return context -> {
@ -297,9 +292,10 @@ public class MongoRepositoryContributor extends RepositoryContributor { @@ -297,9 +292,10 @@ public class MongoRepositoryContributor extends RepositoryContributor {
String variableName = context.localVariable("aggregation");
builder.add(aggregationBlockBuilder(context, queryMethod).stages(aggregation)
builder.add(aggregationBlockBuilder(context, simpleTypeHolder, queryMethod).stages(aggregation)
.usingAggregationVariableName(variableName).build());
builder.add(aggregationExecutionBlockBuilder(context, queryMethod).referencing(variableName).build());
builder.add(
aggregationExecutionBlockBuilder(context, simpleTypeHolder, queryMethod).referencing(variableName).build());
return builder.build();
};
@ -351,6 +347,7 @@ public class MongoRepositoryContributor extends RepositoryContributor { @@ -351,6 +347,7 @@ public class MongoRepositoryContributor extends RepositoryContributor {
}
static MethodContributor.RepositoryMethodContribution aggregationUpdateMethodContributor(MongoQueryMethod queryMethod,
SimpleTypeHolder simpleTypeHolder,
AggregationUpdateInteraction update) {
return context -> {
@ -364,7 +361,7 @@ public class MongoRepositoryContributor extends RepositoryContributor { @@ -364,7 +361,7 @@ public class MongoRepositoryContributor extends RepositoryContributor {
// update definition
String updateVariableName = context.localVariable("updateDefinition");
builder.add(aggregationBlockBuilder(context, queryMethod).stages(update)
builder.add(aggregationBlockBuilder(context, simpleTypeHolder, queryMethod).stages(update)
.usingAggregationVariableName(updateVariableName).pipelineOnly(true).build());
builder.addStatement("$T $L = $T.from($L.getOperations())", AggregationUpdate.class,

1
spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/aot/Snippet.java

@ -195,7 +195,6 @@ interface Snippet { @@ -195,7 +195,6 @@ interface Snippet {
public BuilderStyleBuilder with(Snippet snippet) {
Assert.notNull(targetMethodName, "TargetMethodName must be set before calling this method");
new BuilderStyleSnippet(targetVariableName, targetMethodName, snippet).appendTo(targetBuilder);
return this;
}

2
spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/MongoQueryCreator.java

@ -375,7 +375,7 @@ public class MongoQueryCreator extends AbstractQueryCreator<Query, Criteria> { @@ -375,7 +375,7 @@ public class MongoQueryCreator extends AbstractQueryCreator<Query, Criteria> {
"Argument for creating $regex pattern for property '%s' must not be null", part.getProperty().getSegment()));
}
if(value instanceof Pattern pattern) {
if (value instanceof Pattern pattern) {
return criteria.regex(pattern);
}

42
spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/AggregationTests.java

@ -15,31 +15,10 @@ @@ -15,31 +15,10 @@
*/
package org.springframework.data.mongodb.core.aggregation;
import static org.springframework.data.domain.Sort.Direction.ASC;
import static org.springframework.data.domain.Sort.Direction.DESC;
import static org.springframework.data.mongodb.core.aggregation.Aggregation.DEFAULT_CONTEXT;
import static org.springframework.data.mongodb.core.aggregation.Aggregation.bind;
import static org.springframework.data.mongodb.core.aggregation.Aggregation.bucket;
import static org.springframework.data.mongodb.core.aggregation.Aggregation.bucketAuto;
import static org.springframework.data.mongodb.core.aggregation.Aggregation.count;
import static org.springframework.data.mongodb.core.aggregation.Aggregation.facet;
import static org.springframework.data.mongodb.core.aggregation.Aggregation.group;
import static org.springframework.data.mongodb.core.aggregation.Aggregation.limit;
import static org.springframework.data.mongodb.core.aggregation.Aggregation.lookup;
import static org.springframework.data.mongodb.core.aggregation.Aggregation.match;
import static org.springframework.data.mongodb.core.aggregation.Aggregation.newAggregation;
import static org.springframework.data.mongodb.core.aggregation.Aggregation.newAggregationOptions;
import static org.springframework.data.mongodb.core.aggregation.Aggregation.out;
import static org.springframework.data.mongodb.core.aggregation.Aggregation.previousOperation;
import static org.springframework.data.mongodb.core.aggregation.Aggregation.project;
import static org.springframework.data.mongodb.core.aggregation.Aggregation.replaceRoot;
import static org.springframework.data.mongodb.core.aggregation.Aggregation.sample;
import static org.springframework.data.mongodb.core.aggregation.Aggregation.skip;
import static org.springframework.data.mongodb.core.aggregation.Aggregation.sort;
import static org.springframework.data.mongodb.core.aggregation.Aggregation.unwind;
import static org.springframework.data.mongodb.core.query.Criteria.where;
import static org.springframework.data.mongodb.test.util.Assertions.assertThat;
import static org.springframework.data.mongodb.test.util.Assertions.assertThatIllegalArgumentException;
import static org.springframework.data.domain.Sort.Direction.*;
import static org.springframework.data.mongodb.core.aggregation.Aggregation.*;
import static org.springframework.data.mongodb.core.query.Criteria.*;
import static org.springframework.data.mongodb.test.util.Assertions.*;
import java.io.BufferedInputStream;
import java.text.ParseException;
@ -67,6 +46,7 @@ import org.bson.Document; @@ -67,6 +46,7 @@ import org.bson.Document;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.core.io.ClassPathResource;
import org.springframework.data.annotation.Id;
import org.springframework.data.domain.Sort;
@ -574,7 +554,7 @@ public class AggregationTests { @@ -574,7 +554,7 @@ public class AggregationTests {
/*
//complex mongodb aggregation framework example from
https://docs.mongodb.org/manual/tutorial/aggregation-examples/#largest-and-smallest-cities-by-state
db.zipcodes.aggregate(
{
$group: {
@ -3116,8 +3096,8 @@ public class AggregationTests { @@ -3116,8 +3096,8 @@ public class AggregationTests {
}
}
@Test
void xxx() {
@Test // GH-5027
void shouldAggregateAsInterface() {
MyOhMy source = new MyOhMy();
source.id = "id-1";
@ -3127,8 +3107,8 @@ public class AggregationTests { @@ -3127,8 +3107,8 @@ public class AggregationTests {
mongoTemplate.save(source);
TypedAggregation<MyOhMy> agg = newAggregation(MyOhMy.class, project("firstname"));
AggregationResults<MyMyOh> aggregate = mongoTemplate.aggregate(agg, MyMyOh.class);
assertThat(aggregate.getMappedResults()).hasOnlyElementsOfType(MyMyOh.class);
AggregationResults<MyMyOhInterface> aggregate = mongoTemplate.aggregate(agg, MyMyOhInterface.class);
assertThat(aggregate.getMappedResults()).hasOnlyElementsOfType(MyMyOhInterface.class);
}
static class MyOhMy {
@ -3137,7 +3117,7 @@ public class AggregationTests { @@ -3137,7 +3117,7 @@ public class AggregationTests {
String lastname;
}
interface MyMyOh {
interface MyMyOhInterface {
String getFirstname();
}
}

Loading…
Cancel
Save