Browse Source

Polishing.

Move Streamable check to QueryBlocks, move off deprecated API.

See #5089
Original pull request: #5090
pull/5093/merge
Mark Paluch 1 month ago
parent
commit
828c7e2ae4
No known key found for this signature in database
GPG Key ID: 55BC6374BAA9D973
  1. 11
      spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/aot/AggregationBlocks.java
  2. 12
      spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/aot/DeleteBlocks.java
  3. 6
      spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/aot/GeoBlocks.java
  4. 40
      spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/aot/MongoCodeBlocks.java
  5. 20
      spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/aot/QueryBlocks.java
  6. 4
      spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/aot/VectorSearchBlocks.java
  7. 11
      spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/DbRefMappingMongoConverterUnitTests.java
  8. 5
      spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/query/BasicQueryUnitTests.java
  9. 11
      spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/PersonRepositoryLazyLoadingIntegrationTests.java

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

@ -41,7 +41,6 @@ import org.springframework.data.mongodb.repository.ReadPreference; @@ -41,7 +41,6 @@ import org.springframework.data.mongodb.repository.ReadPreference;
import org.springframework.data.mongodb.repository.query.MongoQueryMethod;
import org.springframework.data.repository.aot.generate.AotQueryMethodGenerationContext;
import org.springframework.data.util.ReflectionUtils;
import org.springframework.data.util.Streamable;
import org.springframework.javapoet.CodeBlock;
import org.springframework.javapoet.CodeBlock.Builder;
import org.springframework.util.ClassUtils;
@ -146,15 +145,11 @@ class AggregationBlocks { @@ -146,15 +145,11 @@ class AggregationBlocks {
builder.addStatement("return $L.aggregateStream($L, $T.class)", mongoOpsRef, aggregationVariableName,
outputType);
} else {
CodeBlock resultBlock = CodeBlock.of("$L.aggregate($L, $T.class).getMappedResults()", mongoOpsRef,
CodeBlock codeBlock = CodeBlock.of("$L.aggregate($L, $T.class).getMappedResults()", mongoOpsRef,
aggregationVariableName, outputType);
if (queryMethod.getReturnType().getType().equals(Streamable.class)) {
resultBlock = CodeBlock.of("$T.of($L)", Streamable.class, resultBlock);
}
builder.addStatement("return $L", resultBlock);
builder.addStatement("return $L",
MongoCodeBlocks.potentiallyWrapStreamable(context.getMethodReturn(), codeBlock));
}
}
}

12
spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/aot/DeleteBlocks.java

@ -18,17 +18,18 @@ package org.springframework.data.mongodb.repository.aot; @@ -18,17 +18,18 @@ package org.springframework.data.mongodb.repository.aot;
import java.util.Optional;
import org.jspecify.annotations.NullUnmarked;
import org.springframework.core.ResolvableType;
import org.springframework.data.mongodb.core.ExecutableRemoveOperation.ExecutableRemove;
import org.springframework.data.mongodb.core.MongoOperations;
import org.springframework.data.mongodb.repository.query.MongoQueryExecution.DeleteExecution;
import org.springframework.data.mongodb.repository.query.MongoQueryMethod;
import org.springframework.data.repository.aot.generate.AotQueryMethodGenerationContext;
import org.springframework.data.repository.aot.generate.MethodReturn;
import org.springframework.javapoet.CodeBlock;
import org.springframework.javapoet.CodeBlock.Builder;
import org.springframework.javapoet.TypeName;
import org.springframework.util.ClassUtils;
import org.springframework.util.ObjectUtils;
/**
* @author Christoph Strobl
@ -59,12 +60,11 @@ class DeleteBlocks { @@ -59,12 +60,11 @@ class DeleteBlocks {
String mongoOpsRef = context.fieldNameOf(MongoOperations.class);
Builder builder = CodeBlock.builder();
MethodReturn methodReturn = context.getMethodReturn();
Class<?> domainType = context.getRepositoryInformation().getDomainType();
boolean isProjecting = context.getActualReturnType() != null
&& !ObjectUtils.nullSafeEquals(TypeName.get(domainType), context.getActualReturnType());
boolean isProjecting = methodReturn.isProjecting();
Object actualReturnType = isProjecting ? context.getActualReturnType().getType() : domainType;
Object actualReturnType = isProjecting ? methodReturn.getActualTypeName() : domainType;
builder.add("\n");
VariableSnippet remover = Snippet.declare(builder)
@ -83,7 +83,7 @@ class DeleteBlocks { @@ -83,7 +83,7 @@ class DeleteBlocks {
actualReturnType = ClassUtils.isPrimitiveOrWrapper(context.getMethod().getReturnType())
? TypeName.get(context.getMethod().getReturnType())
: queryMethod.isCollectionQuery() ? context.getReturnTypeName() : actualReturnType;
: queryMethod.isCollectionQuery() ? methodReturn.getTypeName() : actualReturnType;
if (ClassUtils.isVoidType(context.getMethod().getReturnType())) {
builder.addStatement("new $T($L, $T.$L).execute($L)", DeleteExecution.class, remover.getVariableName(),

6
spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/aot/GeoBlocks.java

@ -24,6 +24,7 @@ import org.springframework.data.mongodb.core.MongoOperations; @@ -24,6 +24,7 @@ import org.springframework.data.mongodb.core.MongoOperations;
import org.springframework.data.mongodb.core.query.NearQuery;
import org.springframework.data.mongodb.repository.query.MongoQueryMethod;
import org.springframework.data.repository.aot.generate.AotQueryMethodGenerationContext;
import org.springframework.data.repository.aot.generate.MethodReturn;
import org.springframework.data.support.PageableExecutionUtils;
import org.springframework.javapoet.CodeBlock;
import org.springframework.util.ClassUtils;
@ -117,12 +118,13 @@ class GeoBlocks { @@ -117,12 +118,13 @@ class GeoBlocks {
CodeBlock.Builder builder = CodeBlock.builder();
builder.add("\n");
MethodReturn methodReturn = context.getMethodReturn();
VariableSnippet queryExecutor = Snippet.declare(builder).variable(context.localVariable("nearFinder")).as(
"$L.query($T.class).near($L)", context.fieldNameOf(MongoOperations.class),
context.getRepositoryInformation().getDomainType(), queryVariableName);
if (ClassUtils.isAssignable(GeoPage.class, context.getReturnType().getRawClass())) {
if (ClassUtils.isAssignable(GeoPage.class, methodReturn.toClass())) {
VariableSnippet geoResult = Snippet.declare(builder).variable(context.localVariable("geoResult")).as("$L.all()",
queryExecutor.getVariableName());
@ -137,7 +139,7 @@ class GeoBlocks { @@ -137,7 +139,7 @@ class GeoBlocks {
builder.addStatement("return new $T<>($L, $L, $L.getTotalElements())", GeoPage.class,
geoResult.getVariableName(), context.getPageableParameterName(), resultPage.getVariableName());
} else if (ClassUtils.isAssignable(GeoResults.class, context.getReturnType().getRawClass())) {
} else if (ClassUtils.isAssignable(GeoResults.class, methodReturn.toClass())) {
builder.addStatement("return $L.all()", queryExecutor.getVariableName());
} else {
builder.addStatement("return $L.all().getContent()", queryExecutor.getVariableName());

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

@ -34,6 +34,8 @@ import org.springframework.data.mongodb.repository.aot.UpdateBlocks.UpdateExecut @@ -34,6 +34,8 @@ import org.springframework.data.mongodb.repository.aot.UpdateBlocks.UpdateExecut
import org.springframework.data.mongodb.repository.query.MongoQueryMethod;
import org.springframework.data.repository.aot.generate.AotQueryMethodGenerationContext;
import org.springframework.data.repository.aot.generate.ExpressionMarker;
import org.springframework.data.repository.aot.generate.MethodReturn;
import org.springframework.data.util.Streamable;
import org.springframework.javapoet.CodeBlock;
import org.springframework.javapoet.CodeBlock.Builder;
import org.springframework.util.NumberUtils;
@ -98,7 +100,6 @@ class MongoCodeBlocks { @@ -98,7 +100,6 @@ class MongoCodeBlocks {
* @return
*/
static UpdateCodeBlockBuilder updateBlockBuilder(AotQueryMethodGenerationContext context) {
return new UpdateCodeBlockBuilder(context);
}
@ -111,44 +112,27 @@ class MongoCodeBlocks { @@ -111,44 +112,27 @@ class MongoCodeBlocks {
*/
static UpdateExecutionCodeBlockBuilder updateExecutionBlockBuilder(AotQueryMethodGenerationContext context,
MongoQueryMethod queryMethod) {
return new UpdateExecutionCodeBlockBuilder(context, queryMethod);
}
/**
* Builder for generating aggregation (pipeline) parsing {@link CodeBlock}.
*
* @param context
* @param simpleTypeHolder
* @param queryMethod
* @return
*/
static AggregationCodeBlockBuilder aggregationBlockBuilder(AotQueryMethodGenerationContext context,
SimpleTypeHolder simpleTypeHolder,
MongoQueryMethod queryMethod) {
SimpleTypeHolder simpleTypeHolder, MongoQueryMethod 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) {
SimpleTypeHolder simpleTypeHolder, MongoQueryMethod queryMethod) {
return new AggregationExecutionCodeBlockBuilder(context, simpleTypeHolder, queryMethod);
}
/**
* Builder for generating {@link org.springframework.data.mongodb.core.query.NearQuery} {@link CodeBlock}.
*
* @param context
* @param queryMethod
* @return
*/
static GeoNearCodeBlockBuilder geoNearBlockBuilder(AotQueryMethodGenerationContext context,
MongoQueryMethod queryMethod) {
@ -159,12 +143,8 @@ class MongoCodeBlocks { @@ -159,12 +143,8 @@ class MongoCodeBlocks {
/**
* Builder for generating {@link org.springframework.data.mongodb.core.query.NearQuery} execution {@link CodeBlock}
* that can return {@link org.springframework.data.geo.GeoResults}.
*
* @param context
* @return
*/
static GeoNearExecutionCodeBlockBuilder geoNearExecutionBlockBuilder(AotQueryMethodGenerationContext context) {
return new GeoNearExecutionCodeBlockBuilder(context);
}
@ -205,6 +185,7 @@ class MongoCodeBlocks { @@ -205,6 +185,7 @@ class MongoCodeBlocks {
static CodeBlock evaluateNumberPotentially(String value, Class<? extends Number> targetType,
AotQueryMethodGenerationContext context) {
try {
Number number = NumberUtils.parseNumber(value, targetType);
return CodeBlock.of("$L", number);
@ -251,4 +232,15 @@ class MongoCodeBlocks { @@ -251,4 +232,15 @@ class MongoCodeBlocks {
readPreference);
}
}
/**
* Wraps the given {@link CodeBlock} representing an {@link Iterable} into a {@link Streamable} if the
* {@link MethodReturn} indicates so.
*/
public static CodeBlock potentiallyWrapStreamable(MethodReturn methodReturn, CodeBlock returningIterable) {
return methodReturn.toClass().equals(Streamable.class)
? CodeBlock.of("$T.of($L)", Streamable.class, returningIterable)
: returningIterable;
}
}

20
spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/aot/QueryBlocks.java

@ -20,6 +20,7 @@ import java.util.Optional; @@ -20,6 +20,7 @@ import java.util.Optional;
import org.bson.Document;
import org.jspecify.annotations.NullUnmarked;
import org.springframework.core.annotation.MergedAnnotation;
import org.springframework.data.domain.ScrollPosition;
import org.springframework.data.mongodb.core.ExecutableFindOperation.FindWithQuery;
@ -33,11 +34,10 @@ import org.springframework.data.mongodb.repository.query.MongoQueryExecution.Pag @@ -33,11 +34,10 @@ import org.springframework.data.mongodb.repository.query.MongoQueryExecution.Pag
import org.springframework.data.mongodb.repository.query.MongoQueryExecution.SlicedExecution;
import org.springframework.data.mongodb.repository.query.MongoQueryMethod;
import org.springframework.data.repository.aot.generate.AotQueryMethodGenerationContext;
import org.springframework.data.repository.aot.generate.MethodReturn;
import org.springframework.data.util.Lazy;
import org.springframework.data.util.Streamable;
import org.springframework.javapoet.CodeBlock;
import org.springframework.javapoet.CodeBlock.Builder;
import org.springframework.javapoet.TypeName;
import org.springframework.util.ClassUtils;
import org.springframework.util.NumberUtils;
import org.springframework.util.StringUtils;
@ -69,6 +69,7 @@ class QueryBlocks { @@ -69,6 +69,7 @@ class QueryBlocks {
CodeBlock build() {
MethodReturn methodReturn = context.getMethodReturn();
String mongoOpsRef = context.fieldNameOf(MongoOperations.class);
Builder builder = CodeBlock.builder();
@ -76,7 +77,7 @@ class QueryBlocks { @@ -76,7 +77,7 @@ class QueryBlocks {
boolean isProjecting = context.getReturnedType().isProjecting();
Class<?> domainType = context.getRepositoryInformation().getDomainType();
Object actualReturnType = queryMethod.getParameters().hasDynamicProjection() || isProjecting
? TypeName.get(context.getActualReturnType().getType())
? methodReturn.getActualTypeName()
: domainType;
builder.add("\n");
@ -105,10 +106,10 @@ class QueryBlocks { @@ -105,10 +106,10 @@ class QueryBlocks {
terminatingMethod = "stream()";
} else {
if (query.getQuery().isLimited()) {
terminatingMethod = Optional.class.isAssignableFrom(context.getReturnType().toClass()) ? "first()"
terminatingMethod = Optional.class.isAssignableFrom(methodReturn.toClass()) ? "first()"
: "firstValue()";
} else {
terminatingMethod = Optional.class.isAssignableFrom(context.getReturnType().toClass()) ? "one()"
terminatingMethod = Optional.class.isAssignableFrom(methodReturn.toClass()) ? "one()"
: "oneValue()";
}
}
@ -139,7 +140,8 @@ class QueryBlocks { @@ -139,7 +140,8 @@ class QueryBlocks {
}
}
} else {
if (query.isCount() && !ClassUtils.isAssignable(Long.class, context.getActualReturnType().getRawClass())) {
if (query.isCount() && !ClassUtils.isAssignable(Long.class, methodReturn.getActualReturnClass())) {
Class<?> returnType = ClassUtils.resolvePrimitiveIfNecessary(queryMethod.getReturnedObjectType());
builder.addStatement("return $T.convertNumberToTargetClass($L.matching($L).$L, $T.class)", NumberUtils.class,
@ -150,11 +152,7 @@ class QueryBlocks { @@ -150,11 +152,7 @@ class QueryBlocks {
CodeBlock resultBlock = CodeBlock.of("$L.matching($L).$L", context.localVariable("finder"), query.name(),
terminatingMethod);
if (queryMethod.getReturnType().getType().equals(Streamable.class)) {
resultBlock = CodeBlock.of("$T.of($L)", Streamable.class, resultBlock);
}
builder.addStatement("return $L", resultBlock);
builder.addStatement("return $L", MongoCodeBlocks.potentiallyWrapStreamable(methodReturn, resultBlock));
}
}

4
spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/aot/VectorSearchBlocks.java

@ -166,10 +166,10 @@ class VectorSearchBlocks { @@ -166,10 +166,10 @@ class VectorSearchBlocks {
builder.indent();
builder.add("$1T $4L = $5L.getMappedObject(parse($2S), $3T.class);\n", Document.class, filter.getSortString(),
context.getActualReturnType().getType(), mappedSort, ctx);
context.getMethodReturn().getActualClassName(), mappedSort, ctx);
builder.add("return new $1T($2S, $3L.append(\"__score__\", -1));\n", Document.class, "$sort", mappedSort);
builder.unindent();
builder.add("};");
builder.add("}");
return new ExpressionSnippet(builder.build());
}

11
spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/DbRefMappingMongoConverterUnitTests.java

@ -36,9 +36,8 @@ import org.bson.conversions.Bson; @@ -36,9 +36,8 @@ import org.bson.conversions.Bson;
import org.bson.types.ObjectId;
import org.jspecify.annotations.Nullable;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.condition.DisabledForJreRange;
import org.junit.jupiter.api.condition.JRE;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.Mock;
import org.mockito.Mockito;
@ -186,7 +185,7 @@ class DbRefMappingMongoConverterUnitTests { @@ -186,7 +185,7 @@ class DbRefMappingMongoConverterUnitTests {
}
@Test // DATAMONGO-348
@DisabledForJreRange(min = JRE.JAVA_16, disabledReason = "Class Proxies for eg; ArrayList require to open java.util.")
@Disabled("Class Proxies for eg; ArrayList require to open java.util.")
void lazyLoadingProxyForLazyDbRefOnConcreteCollection() {
String id = "42";
@ -514,7 +513,7 @@ class DbRefMappingMongoConverterUnitTests { @@ -514,7 +513,7 @@ class DbRefMappingMongoConverterUnitTests {
}
@Test // DATAMONGO-1076
@DisabledForJreRange(min = JRE.JAVA_16, disabledReason = "Class Proxies for eg; ArrayList require to open java.util.")
@Disabled("Class Proxies for eg; ArrayList require to open java.util.")
void shouldNotTriggerResolvingOfLazyLoadedProxyWhenFinalizeMethodIsInvoked() throws Exception {
MongoPersistentEntity<?> entity = mappingContext
@ -533,7 +532,7 @@ class DbRefMappingMongoConverterUnitTests { @@ -533,7 +532,7 @@ class DbRefMappingMongoConverterUnitTests {
}
@Test // DATAMONGO-1194
@DisabledForJreRange(min = JRE.JAVA_16, disabledReason = "Class Proxies for eg; ArrayList require to open java.util.")
@Disabled("Class Proxies for eg; ArrayList require to open java.util.")
void shouldBulkFetchListOfReferences() {
String id1 = "1";
@ -584,7 +583,7 @@ class DbRefMappingMongoConverterUnitTests { @@ -584,7 +583,7 @@ class DbRefMappingMongoConverterUnitTests {
}
@Test // DATAMONGO-1194
@DisabledForJreRange(min = JRE.JAVA_16, disabledReason = "Class Proxies for eg; ArrayList require to open java.util.")
@Disabled("Class Proxies for eg; ArrayList require to open java.util.")
void shouldFallbackToOneByOneFetchingWhenElementsInListOfReferencesPointToDifferentCollections() {
String id1 = "1";

5
spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/query/BasicQueryUnitTests.java

@ -22,10 +22,9 @@ import nl.jqno.equalsverifier.EqualsVerifier; @@ -22,10 +22,9 @@ import nl.jqno.equalsverifier.EqualsVerifier;
import nl.jqno.equalsverifier.Warning;
import org.bson.Document;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.condition.DisabledForJreRange;
import org.junit.jupiter.api.condition.JRE;
import org.springframework.data.domain.Sort;
import org.springframework.data.domain.Sort.Direction;
@ -66,7 +65,7 @@ public class BasicQueryUnitTests { @@ -66,7 +65,7 @@ public class BasicQueryUnitTests {
}
@Test // DATAMONGO-1093
@DisabledForJreRange(min = JRE.JAVA_16, disabledReason = "EqualsVerifier uses reflection on Optional")
@Disabled("EqualsVerifier uses reflection on Optional")
public void equalsContract() {
BasicQuery query1 = new BasicQuery("{ \"name\" : \"Thomas\"}", "{\"name\":1, \"age\":1}");

11
spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/PersonRepositoryLazyLoadingIntegrationTests.java

@ -15,19 +15,18 @@ @@ -15,19 +15,18 @@
*/
package org.springframework.data.mongodb.repository;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatNoException;
import static org.springframework.data.mongodb.core.convert.LazyLoadingTestUtils.assertProxyIsResolved;
import static org.assertj.core.api.Assertions.*;
import static org.springframework.data.mongodb.core.convert.LazyLoadingTestUtils.*;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.condition.DisabledForJreRange;
import org.junit.jupiter.api.condition.JRE;
import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.mongodb.core.MongoOperations;
import org.springframework.test.context.ContextConfiguration;
@ -78,7 +77,7 @@ public class PersonRepositoryLazyLoadingIntegrationTests { @@ -78,7 +77,7 @@ public class PersonRepositoryLazyLoadingIntegrationTests {
}
@Test // DATAMONGO-348
@DisabledForJreRange(min = JRE.JAVA_16, disabledReason = "Class Proxies for eg; ArrayList require to open java.util.")
@Disabled("Class Proxies for eg; ArrayList require to open java.util.")
public void shouldLoadAssociationWithDbRefOnConcreteCollectionAndLazyLoadingEnabled() {
User thomas = new User();

Loading…
Cancel
Save