From 403f0019d55dd5b70d7132549f82acb8ae16d6bb Mon Sep 17 00:00:00 2001 From: Christoph Strobl Date: Wed, 23 Jun 2021 15:45:14 +0200 Subject: [PATCH] Fix Optional handling in query creation and result processing. Original pull request: #3687. Resolves #3656 --- .../core/mapping/MongoMappingContext.java | 6 ++++ .../mapping/MongoMappingContextUnitTests.java | 31 +++++++++++++++++++ ...tractPersonRepositoryIntegrationTests.java | 13 ++++++++ .../mongodb/repository/PersonRepository.java | 2 ++ .../repository/PersonSummaryWithOptional.java | 24 ++++++++++++++ 5 files changed, 76 insertions(+) create mode 100644 spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/PersonSummaryWithOptional.java diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/MongoMappingContext.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/MongoMappingContext.java index c20443480..38381fb99 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/MongoMappingContext.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/MongoMappingContext.java @@ -26,6 +26,7 @@ import org.springframework.data.mapping.model.FieldNamingStrategy; import org.springframework.data.mapping.model.Property; import org.springframework.data.mapping.model.PropertyNameFieldNamingStrategy; import org.springframework.data.mapping.model.SimpleTypeHolder; +import org.springframework.data.util.NullableWrapperConverters; import org.springframework.data.util.TypeInformation; import org.springframework.lang.Nullable; @@ -69,6 +70,11 @@ public class MongoMappingContext extends AbstractMappingContext type) { + + if(NullableWrapperConverters.supports(type.getType())) { + return false; + } + return !MongoSimpleTypes.HOLDER.isSimpleType(type.getType()) && !AbstractMap.class.isAssignableFrom(type.getType()); } diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/MongoMappingContextUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/MongoMappingContextUnitTests.java index a7e454c52..f0cc1a2f3 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/MongoMappingContextUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/MongoMappingContextUnitTests.java @@ -22,6 +22,7 @@ import java.util.AbstractMap; import java.util.Collections; import java.util.Locale; import java.util.Map; +import java.util.Optional; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; @@ -35,6 +36,7 @@ import org.springframework.data.mapping.PersistentProperty; import org.springframework.data.mapping.model.FieldNamingStrategy; import com.mongodb.DBRef; +import org.springframework.data.util.TypeInformation; /** * Unit tests for {@link MongoMappingContext}. @@ -173,6 +175,26 @@ public class MongoMappingContextUnitTests { assertThat(context.getPersistentEntity(ChronoUnit.class)).isNull(); } + @Test // GH-3656 + void shouldNotCreateEntityForOptionalGetter() { + + MongoMappingContext context = new MongoMappingContext(); + MongoPersistentEntity entity = context.getRequiredPersistentEntity(InterfaceWithMethodReturningOptional.class); + + assertThat(context.getPersistentEntities()).map(it -> it.getType()).doesNotContain((Class) + Optional.class).contains((Class)Person.class); + } + + @Test // GH-3656 + void shouldNotCreateEntityForOptionalField() { + + MongoMappingContext context = new MongoMappingContext(); + MongoPersistentEntity entity = context.getRequiredPersistentEntity(ClassWithOptionalField.class); + + assertThat(context.getPersistentEntities()).map(it -> it.getType()).doesNotContain((Class) + Optional.class).contains((Class)Person.class); + } + public class SampleClass { Map children; @@ -244,4 +266,13 @@ public class MongoMappingContextUnitTests { ChronoUnit unit; } + + interface InterfaceWithMethodReturningOptional { + + Optional getPerson(); + } + + class ClassWithOptionalField { + Optional person; + } } diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/AbstractPersonRepositoryIntegrationTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/AbstractPersonRepositoryIntegrationTests.java index d57691385..e462458ae 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/AbstractPersonRepositoryIntegrationTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/AbstractPersonRepositoryIntegrationTests.java @@ -1460,4 +1460,17 @@ public abstract class AbstractPersonRepositoryIntegrationTests { List result = repository.findBySpiritAnimal(dave); assertThat(result).map(Person::getId).containsExactly(josh.getId()); } + + @Test //GH-3656 + void resultProjectionWithOptionalIsExcecutedCorrectly() { + + carter.setAddress(new Address("batman", "robin", "gotham")); + repository.save(carter); + + PersonSummaryWithOptional result = repository.findSummaryWithOptionalByLastname("Beauford"); + + assertThat(result).isNotNull(); + assertThat(result.getAddress()).isPresent(); + assertThat(result.getFirstname()).contains("Carter"); + } } diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/PersonRepository.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/PersonRepository.java index 155cf7a7b..9ac128208 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/PersonRepository.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/PersonRepository.java @@ -307,6 +307,8 @@ public interface PersonRepository extends MongoRepository, Query // DATAMONGO-1030 PersonSummaryDto findSummaryByLastname(String lastname); + PersonSummaryWithOptional findSummaryWithOptionalByLastname(String lastname); + @Query("{ ?0 : ?1 }") List findByKeyValue(String key, String value); diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/PersonSummaryWithOptional.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/PersonSummaryWithOptional.java new file mode 100644 index 000000000..d6a98752b --- /dev/null +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/PersonSummaryWithOptional.java @@ -0,0 +1,24 @@ +/* + * Copyright 2021 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.repository; + +import java.util.Optional; + +public interface PersonSummaryWithOptional { + + Optional
getAddress(); + Optional getFirstname(); +}