diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/MongoConfigurationSupport.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/MongoConfigurationSupport.java index 60c3ca38c..33b2e5c9e 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/MongoConfigurationSupport.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/MongoConfigurationSupport.java @@ -20,7 +20,6 @@ import java.util.Collections; import java.util.HashSet; import java.util.Set; -import org.bson.UuidRepresentation; import org.springframework.beans.factory.config.BeanDefinition; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider; @@ -226,7 +225,6 @@ public abstract class MongoConfigurationSupport { protected MongoClientSettings mongoClientSettings() { MongoClientSettings.Builder builder = MongoClientSettings.builder(); - builder.uuidRepresentation(UuidRepresentation.STANDARD); configureClientSettings(builder); return builder.build(); } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoClientFactoryBean.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoClientFactoryBean.java index 7c6639630..e9cb21e70 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoClientFactoryBean.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoClientFactoryBean.java @@ -23,8 +23,8 @@ import java.util.function.Consumer; import java.util.function.Function; import java.util.stream.Collectors; -import org.bson.UuidRepresentation; import org.jspecify.annotations.Nullable; + import org.springframework.beans.factory.config.AbstractFactoryBean; import org.springframework.dao.DataAccessException; import org.springframework.dao.support.PersistenceExceptionTranslator; @@ -162,7 +162,6 @@ public class MongoClientFactoryBean extends AbstractFactoryBean imp getOrDefault(port, "" + ServerAddress.defaultPort()))); Builder builder = MongoClientSettings.builder().applyConnectionString(connectionString); - builder.uuidRepresentation(UuidRepresentation.STANDARD); if (mongoClientSettings != null) { diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/MongoConverters.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/MongoConverters.java index 1fd45e196..36a335cce 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/MongoConverters.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/MongoConverters.java @@ -23,9 +23,14 @@ import java.net.MalformedURLException; import java.net.URI; import java.net.URL; import java.time.Instant; +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.time.LocalTime; +import java.time.ZoneId; import java.util.ArrayList; import java.util.Collection; import java.util.Currency; +import java.util.Date; import java.util.List; import java.util.UUID; import java.util.concurrent.atomic.AtomicInteger; @@ -83,19 +88,67 @@ abstract class MongoConverters { private MongoConverters() {} /** - * Returns the converters to be registered. + * Returns the {@code Date} to UTC converters to be registered. * * @return - * @since 1.9 + * @since 5.0 */ - static Collection getConvertersToRegister() { + static Collection getDateToUtcConverters() { - List converters = new ArrayList<>(); + List converters = new ArrayList<>(3); + + converters.add(DateToUtcLocalDateConverter.INSTANCE); + converters.add(DateToUtcLocalTimeConverter.INSTANCE); + converters.add(DateToUtcLocalDateTimeConverter.INSTANCE); + + return converters; + } + + /** + * Returns the {@code Decimal128} converters to be registered. + * + * @return + * @since 5.0 + */ + static Collection getBigNumberDecimal128Converters() { + + List converters = new ArrayList<>(3); converters.add(BigDecimalToDecimal128Converter.INSTANCE); converters.add(Decimal128ToBigDecimalConverter.INSTANCE); converters.add(BigIntegerToDecimal128Converter.INSTANCE); + return converters; + } + + /** + * Returns the {@code String} converters to be registered for {@link BigInteger} and {@link BigDecimal}. + * + * @return + * @since 5.0 + */ + static Collection getBigNumberStringConverters() { + + List converters = new ArrayList<>(4); + + converters.add(BigDecimalToStringConverter.INSTANCE); + converters.add(StringToBigDecimalConverter.INSTANCE); + converters.add(BigIntegerToStringConverter.INSTANCE); + converters.add(StringToBigIntegerConverter.INSTANCE); + + return converters; + } + + /** + * Returns the converters to be registered. + * + * @return + * @since 1.9 + */ + static Collection getConvertersToRegister() { + + List converters = new ArrayList<>(); + converters.add(URLToStringConverter.INSTANCE); converters.add(StringToURLConverter.INSTANCE); converters.add(DocumentToStringConverter.INSTANCE); @@ -630,4 +683,35 @@ abstract class MongoConverters { return Instant.ofEpochSecond(source.getTime(), 0); } } + + @ReadingConverter + private enum DateToUtcLocalDateTimeConverter implements Converter { + + INSTANCE; + + @Override + public LocalDateTime convert(Date source) { + return LocalDateTime.ofInstant(Instant.ofEpochMilli(source.getTime()), ZoneId.of("UTC")); + } + } + + @ReadingConverter + private enum DateToUtcLocalTimeConverter implements Converter { + INSTANCE; + + @Override + public LocalTime convert(Date source) { + return DateToUtcLocalDateTimeConverter.INSTANCE.convert(source).toLocalTime(); + } + } + + @ReadingConverter + private enum DateToUtcLocalDateConverter implements Converter { + INSTANCE; + + @Override + public LocalDate convert(Date source) { + return DateToUtcLocalDateTimeConverter.INSTANCE.convert(source).toLocalDate(); + } + } } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/MongoCustomConversions.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/MongoCustomConversions.java index f7af94728..a54619155 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/MongoCustomConversions.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/MongoCustomConversions.java @@ -15,7 +15,6 @@ */ package org.springframework.data.mongodb.core.convert; -import java.time.Instant; import java.time.LocalDate; import java.time.LocalDateTime; import java.time.LocalTime; @@ -33,6 +32,7 @@ import java.util.Set; import java.util.function.Consumer; import org.jspecify.annotations.Nullable; + import org.springframework.core.convert.TypeDescriptor; import org.springframework.core.convert.converter.Converter; import org.springframework.core.convert.converter.ConverterFactory; @@ -42,14 +42,9 @@ import org.springframework.data.convert.PropertyValueConversions; import org.springframework.data.convert.PropertyValueConverter; import org.springframework.data.convert.PropertyValueConverterFactory; import org.springframework.data.convert.PropertyValueConverterRegistrar; -import org.springframework.data.convert.ReadingConverter; import org.springframework.data.convert.SimplePropertyValueConversions; import org.springframework.data.convert.WritingConverter; import org.springframework.data.mapping.model.SimpleTypeHolder; -import org.springframework.data.mongodb.core.convert.MongoConverters.BigDecimalToStringConverter; -import org.springframework.data.mongodb.core.convert.MongoConverters.BigIntegerToStringConverter; -import org.springframework.data.mongodb.core.convert.MongoConverters.StringToBigDecimalConverter; -import org.springframework.data.mongodb.core.convert.MongoConverters.StringToBigIntegerConverter; import org.springframework.data.mongodb.core.mapping.MongoPersistentProperty; import org.springframework.data.mongodb.core.mapping.MongoSimpleTypes; import org.springframework.lang.Contract; @@ -68,7 +63,6 @@ import org.springframework.util.Assert; */ public class MongoCustomConversions extends org.springframework.data.convert.CustomConversions { - private static final StoreConversions STORE_CONVERSIONS; private static final List STORE_CONVERTERS; static { @@ -80,7 +74,6 @@ public class MongoCustomConversions extends org.springframework.data.convert.Cus converters.addAll(GeoConverters.getConvertersToRegister()); STORE_CONVERTERS = Collections.unmodifiableList(converters); - STORE_CONVERSIONS = StoreConversions.of(MongoSimpleTypes.HOLDER, STORE_CONVERTERS); } /** @@ -156,7 +149,8 @@ public class MongoCustomConversions extends org.springframework.data.convert.Cus * List of {@literal java.time} types having different representation when rendered via the native * {@link org.bson.codecs.Codec} than the Spring Data {@link Converter}. */ - private static final Set> JAVA_DRIVER_TIME_SIMPLE_TYPES = Set.of(LocalDate.class, LocalTime.class, LocalDateTime.class); + private static final Set> JAVA_DRIVER_TIME_SIMPLE_TYPES = Set.of(LocalDate.class, LocalTime.class, + LocalDateTime.class); private boolean useNativeDriverJavaTimeCodecs = false; private BigDecimalRepresentation bigDecimals = BigDecimalRepresentation.DECIMAL128; @@ -326,6 +320,7 @@ public class MongoCustomConversions extends org.springframework.data.convert.Cus this.bigDecimals = representation; return this; } + /** * Optionally set the {@link PropertyValueConversions} to be applied during mapping. *

@@ -375,72 +370,40 @@ public class MongoCustomConversions extends org.springframework.data.convert.Cus svc.init(); } - List converters = new ArrayList<>(STORE_CONVERTERS.size() + 7); + List storeConverters = new ArrayList<>(STORE_CONVERTERS.size() + 10); if (bigDecimals == BigDecimalRepresentation.STRING) { - - converters.add(BigDecimalToStringConverter.INSTANCE); - converters.add(StringToBigDecimalConverter.INSTANCE); - converters.add(BigIntegerToStringConverter.INSTANCE); - converters.add(StringToBigIntegerConverter.INSTANCE); + storeConverters.addAll(MongoConverters.getBigNumberStringConverters()); } - if (!useNativeDriverJavaTimeCodecs) { - - converters.addAll(customConverters); - return new ConverterConfiguration(STORE_CONVERSIONS, converters, convertiblePair -> true, - this.propertyValueConversions); + if (bigDecimals == BigDecimalRepresentation.DECIMAL128) { + storeConverters.addAll(MongoConverters.getBigNumberDecimal128Converters()); } - /* - * We need to have those converters using UTC as the default ones would go on with the systemDefault. - */ - converters.add(DateToUtcLocalDateConverter.INSTANCE); - converters.add(DateToUtcLocalTimeConverter.INSTANCE); - converters.add(DateToUtcLocalDateTimeConverter.INSTANCE); - converters.addAll(STORE_CONVERTERS); + if (useNativeDriverJavaTimeCodecs) { - StoreConversions storeConversions = StoreConversions - .of(new SimpleTypeHolder(JAVA_DRIVER_TIME_SIMPLE_TYPES, MongoSimpleTypes.HOLDER), converters); + /* + * We need to have those converters using UTC as the default ones would go on with the systemDefault. + */ + storeConverters.addAll(MongoConverters.getDateToUtcConverters()); + storeConverters.addAll(STORE_CONVERTERS); - return new ConverterConfiguration(storeConversions, this.customConverters, convertiblePair -> { + StoreConversions storeConversions = StoreConversions + .of(new SimpleTypeHolder(JAVA_DRIVER_TIME_SIMPLE_TYPES, MongoSimpleTypes.HOLDER), storeConverters); - // Avoid default registrations + return new ConverterConfiguration(storeConversions, this.customConverters, convertiblePair -> { + + // Avoid default registrations return !JAVA_DRIVER_TIME_SIMPLE_TYPES.contains(convertiblePair.getSourceType()) || !Date.class.isAssignableFrom(convertiblePair.getTargetType()); }, this.propertyValueConversions); - } - - @ReadingConverter - private enum DateToUtcLocalDateTimeConverter implements Converter { - - INSTANCE; - @Override - public LocalDateTime convert(Date source) { - return LocalDateTime.ofInstant(Instant.ofEpochMilli(source.getTime()), ZoneId.of("UTC")); } - } - - @ReadingConverter - private enum DateToUtcLocalTimeConverter implements Converter { - INSTANCE; - @Override - public LocalTime convert(Date source) { - return DateToUtcLocalDateTimeConverter.INSTANCE.convert(source).toLocalTime(); - } - } - - @ReadingConverter - private enum DateToUtcLocalDateConverter implements Converter { - INSTANCE; - - @Override - public LocalDate convert(Date source) { - return DateToUtcLocalDateTimeConverter.INSTANCE.convert(source).toLocalDate(); - } + storeConverters.addAll(STORE_CONVERTERS); + return new ConverterConfiguration(StoreConversions.of(MongoSimpleTypes.createSimpleTypeHolder(), storeConverters), + this.customConverters, convertiblePair -> true, this.propertyValueConversions); } private boolean hasDefaultPropertyValueConversions() { diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/MongoSimpleTypes.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/MongoSimpleTypes.java index 6b4d9b9e9..aeb79fde4 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/MongoSimpleTypes.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/MongoSimpleTypes.java @@ -62,22 +62,27 @@ public abstract class MongoSimpleTypes { BsonTimestamp.class, Geometry.class, GeometryCollection.class, LineString.class, MultiLineString.class, MultiPoint.class, MultiPolygon.class, Point.class, Polygon.class); - public static final SimpleTypeHolder HOLDER = new SimpleTypeHolder(MONGO_SIMPLE_TYPES, true) { + public static final SimpleTypeHolder HOLDER = createSimpleTypeHolder(); - @Override - public boolean isSimpleType(Class type) { + public static SimpleTypeHolder createSimpleTypeHolder() { - if (type.isEnum()) { - return true; - } + return new SimpleTypeHolder(MONGO_SIMPLE_TYPES, true) { - if (type.getName().startsWith("java.time")) { - return false; - } + @Override + public boolean isSimpleType(Class type) { + + if (type.isEnum()) { + return true; + } - return super.isSimpleType(type); - } - }; + if (type.getName().startsWith("java.time")) { + return false; + } + + return super.isSimpleType(type); + } + }; + } private MongoSimpleTypes() {} } diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/AotPersonRepositoryIntegrationTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/AotPersonRepositoryIntegrationTests.java index bac2bde26..87b9f04ae 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/AotPersonRepositoryIntegrationTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/AotPersonRepositoryIntegrationTests.java @@ -17,6 +17,7 @@ package org.springframework.data.mongodb.repository; import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; + import org.springframework.context.ApplicationContext; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; diff --git a/spring-data-mongodb/src/test/resources/org/springframework/data/mongodb/config/MongoClientNamespaceTests-context.xml b/spring-data-mongodb/src/test/resources/org/springframework/data/mongodb/config/MongoClientNamespaceTests-context.xml index 79e5ac40a..fcf8a258d 100644 --- a/spring-data-mongodb/src/test/resources/org/springframework/data/mongodb/config/MongoClientNamespaceTests-context.xml +++ b/spring-data-mongodb/src/test/resources/org/springframework/data/mongodb/config/MongoClientNamespaceTests-context.xml @@ -3,10 +3,8 @@ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:mongo="http://www.springframework.org/schema/data/mongo" xmlns:context="http://www.springframework.org/schema/context" - xmlns:util="http://www.springframework.org/schema/util" xsi:schemaLocation="http://www.springframework.org/schema/data/mongo https://www.springframework.org/schema/data/mongo/spring-mongo.xsd http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd - http://www.springframework.org/schema/util https://www.springframework.org/schema/util/spring-util.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd"> - + @@ -26,8 +25,8 @@ - - @@ -56,9 +55,9 @@ - + - + diff --git a/spring-data-mongodb/src/test/resources/org/springframework/data/mongodb/repository/PersonRepositoryIntegrationTests-context.xml b/spring-data-mongodb/src/test/resources/org/springframework/data/mongodb/repository/PersonRepositoryIntegrationTests-context.xml index 8c6194f0a..a0451bb97 100644 --- a/spring-data-mongodb/src/test/resources/org/springframework/data/mongodb/repository/PersonRepositoryIntegrationTests-context.xml +++ b/spring-data-mongodb/src/test/resources/org/springframework/data/mongodb/repository/PersonRepositoryIntegrationTests-context.xml @@ -1,12 +1,20 @@ + + + + + + diff --git a/spring-data-mongodb/src/test/resources/org/springframework/data/mongodb/repository/PersonRepositoryIntegrationTests-infrastructure.xml b/spring-data-mongodb/src/test/resources/org/springframework/data/mongodb/repository/PersonRepositoryIntegrationTests-infrastructure.xml index 81a7c261f..c802ee7c3 100644 --- a/spring-data-mongodb/src/test/resources/org/springframework/data/mongodb/repository/PersonRepositoryIntegrationTests-infrastructure.xml +++ b/spring-data-mongodb/src/test/resources/org/springframework/data/mongodb/repository/PersonRepositoryIntegrationTests-infrastructure.xml @@ -7,8 +7,6 @@ http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/util https://www.springframework.org/schema/util/spring-util.xsd"> - - diff --git a/spring-data-mongodb/src/test/resources/org/springframework/data/mongodb/repository/config/MongoNamespaceIntegrationTests-context.xml b/spring-data-mongodb/src/test/resources/org/springframework/data/mongodb/repository/config/MongoNamespaceIntegrationTests-context.xml index b70efb607..2993ee1e4 100644 --- a/spring-data-mongodb/src/test/resources/org/springframework/data/mongodb/repository/config/MongoNamespaceIntegrationTests-context.xml +++ b/spring-data-mongodb/src/test/resources/org/springframework/data/mongodb/repository/config/MongoNamespaceIntegrationTests-context.xml @@ -9,7 +9,11 @@ http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/util https://www.springframework.org/schema/util/spring-util.xsd"> - + + + + + diff --git a/src/main/antora/modules/ROOT/pages/mongodb/mapping/mapping.adoc b/src/main/antora/modules/ROOT/pages/mongodb/mapping/mapping.adoc index 121c80d56..2056dfa20 100644 --- a/src/main/antora/modules/ROOT/pages/mongodb/mapping/mapping.adoc +++ b/src/main/antora/modules/ROOT/pages/mongodb/mapping/mapping.adoc @@ -119,7 +119,7 @@ See xref:mongodb/mapping/custom-conversions.adoc[Custom Conversions - Overriding | native | `{"bin" : { "$binary" : "AQIDBA==", "$type" : "00" }}` -| `java.util.UUID` (Standard UUID) +| `java.util.UUID` (According to UuidRepresentation) | native | `{"uuid" : { "$binary" : "MEaf1CFQ6lSphaa3b9AtlA==", "$type" : "04" }}` @@ -164,13 +164,13 @@ calling `get()` before the actual conversion | `{"value" : "741" }` | `BigInteger` -| converter + -`NumberDecimal`, `String` +| native + +`NumberDecimal`, `String` (see `BigDecimalRepresentation`) | `{"value" : NumberDecimal(741) }`, `{"value" : "741" }` | `BigDecimal` -| converter + -`NumberDecimal`, `String` +| native + +`NumberDecimal`, `String` (see `BigDecimalRepresentation`) | `{"value" : NumberDecimal(741.99) }`, `{"value" : "741.99" }` | `URL` @@ -200,25 +200,21 @@ calling `get()` before the actual conversion | `{"date" : ISODate("2019-11-12T23:00:00.809Z")}` | `Instant` + -(Joda, JSR310-BackPort) +(Java 8) | converter | `{"date" : ISODate("2019-11-12T23:00:00.809Z")}` | `LocalDate` + -(Joda, Java 8, JSR310-BackPort) -| converter / native (Java8)footnote:[Uses UTC zone offset. Configure via xref:mongodb/mapping/mapping.adoc#mapping-configuration[MongoConverterConfigurationAdapter]] +(Java 8) +| converter / native (Java 8)footnote:[Uses UTC zone offset. Configure via xref:mongodb/mapping/mapping.adoc#mapping-configuration[MongoConverterConfigurationAdapter]] | `{"date" : ISODate("2019-11-12T00:00:00.000Z")}` | `LocalDateTime`, `LocalTime` + -(Joda, Java 8, JSR310-BackPort) -| converter / native (Java8)footnote:[Uses UTC zone offset. Configure via xref:mongodb/mapping/mapping.adoc#mapping-configuration[MongoConverterConfigurationAdapter]] -| `{"date" : ISODate("2019-11-12T23:00:00.809Z")}` - -| `DateTime` (Joda) -| converter +(Java 8) +| converter / native (Java 8)footnote:[Uses UTC zone offset. Configure via xref:mongodb/mapping/mapping.adoc#mapping-configuration[MongoConverterConfigurationAdapter]] | `{"date" : ISODate("2019-11-12T23:00:00.809Z")}` -| `ZoneId` (Java 8, JSR310-BackPort) +| `ZoneId` (Java 8) | converter | `{"zoneId" : "ECT - Europe/Paris"}`