DATAMONGO-2328 - Add missing target type conversions for field level type hints.

We now support Date to Long, Date to ObjectId, Script to String and other conversions for both reading and writing scenarios.

Original pull request: #773.
This commit is contained in:
Christoph Strobl
2019-07-30 10:55:42 +02:00
committed by Mark Paluch
parent 2365dba8d9
commit 0a0ee417ac
2 changed files with 135 additions and 6 deletions

View File

@@ -15,8 +15,12 @@
*/
package org.springframework.data.mongodb.core.convert;
import java.math.BigInteger;
import static org.springframework.data.convert.ConverterBuilder.*;
import java.math.BigInteger;
import java.util.Date;
import org.bson.types.Code;
import org.bson.types.ObjectId;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.core.convert.ConversionService;
@@ -93,6 +97,21 @@ public abstract class AbstractMongoConverter implements MongoConverter, Initiali
conversionService.addConverter(BigIntegerToObjectIdConverter.INSTANCE);
}
if (!conversionService.canConvert(Date.class, Long.class)) {
conversionService.addConverter(writing(Date.class, Long.class, Date::getTime).getWritingConverter());
}
if (!conversionService.canConvert(Long.class, Date.class)) {
conversionService.addConverter(reading(Long.class, Date.class, Date::new).getReadingConverter());
}
if (!conversionService.canConvert(ObjectId.class, Date.class)) {
conversionService.addConverter(
reading(ObjectId.class, Date.class, objectId -> new Date(objectId.getTimestamp())).getReadingConverter());
}
conversionService.addConverter(reading(Code.class, String.class, Code::getCode).getReadingConverter());
conversions.registerConvertersIn(conversionService);
}

View File

@@ -40,7 +40,6 @@ import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.junit.MockitoJUnitRunner;
import org.springframework.aop.framework.ProxyFactory;
import org.springframework.beans.ConversionNotSupportedException;
import org.springframework.beans.factory.annotation.Value;
@@ -1943,6 +1942,16 @@ public class MappingMongoConverterUnitTests {
assertThat(target.get("script")).isEqualTo(new Code(source.script));
}
@Test // DATAMONGO-2328
public void readsScriptAsStringWhenAnnotatedWithFieldTargetType() {
String reference = "if (a > b) a else b";
WithExplicitTargetTypes target = converter.read(WithExplicitTargetTypes.class,
new org.bson.Document("script", new Code(reference)));
assertThat(target.script).isEqualTo(reference);
}
@Test // DATAMONGO-1849
public void mapsCollectionValueToExplicitTargetType() {
@@ -1968,6 +1977,96 @@ public class MappingMongoConverterUnitTests {
assertThat(target.get("bigDecimal")).isEqualTo(new Decimal128(source.bigDecimal));
}
@Test // DATAMONGO-2328
public void mapsDateToLongWhenAnnotatedWithFieldTargetType() {
WithExplicitTargetTypes source = new WithExplicitTargetTypes();
source.dateAsLong = new Date();
org.bson.Document target = new org.bson.Document();
converter.write(source, target);
assertThat(target.get("dateAsLong")).isEqualTo(source.dateAsLong.getTime());
}
@Test // DATAMONGO-2328
public void readsLongAsDateWhenAnnotatedWithFieldTargetType() {
Date reference = new Date();
WithExplicitTargetTypes target = converter.read(WithExplicitTargetTypes.class,
new org.bson.Document("dateAsLong", reference.getTime()));
assertThat(target.dateAsLong).isEqualTo(reference);
}
@Test // DATAMONGO-2328
public void mapsLongToDateWhenAnnotatedWithFieldTargetType() {
Date date = new Date();
WithExplicitTargetTypes source = new WithExplicitTargetTypes();
source.longAsDate = date.getTime();
org.bson.Document target = new org.bson.Document();
converter.write(source, target);
assertThat(target.get("longAsDate")).isEqualTo(date);
}
@Test // DATAMONGO-2328
public void readsDateAsLongWhenAnnotatedWithFieldTargetType() {
Date reference = new Date();
WithExplicitTargetTypes target = converter.read(WithExplicitTargetTypes.class,
new org.bson.Document("longAsDate", reference));
assertThat(target.longAsDate).isEqualTo(reference.getTime());
}
@Test // DATAMONGO-2328
public void mapsStringAsBooleanWhenAnnotatedWithFieldTargetType() {
WithExplicitTargetTypes source = new WithExplicitTargetTypes();
source.stringAsBoolean = "true";
org.bson.Document target = new org.bson.Document();
converter.write(source, target);
assertThat(target.get("stringAsBoolean")).isEqualTo(true);
}
@Test // DATAMONGO-2328
public void readsBooleanAsStringWhenAnnotatedWithFieldTargetType() {
WithExplicitTargetTypes target = converter.read(WithExplicitTargetTypes.class,
new org.bson.Document("stringAsBoolean", true));
assertThat(target.stringAsBoolean).isEqualTo("true");
}
@Test // DATAMONGO-2328
public void mapsDateAsObjectIdWhenAnnotatedWithFieldTargetType() {
WithExplicitTargetTypes source = new WithExplicitTargetTypes();
source.dateAsObjectId = new Date();
org.bson.Document target = new org.bson.Document();
converter.write(source, target);
// need to compare the the timestamp as ObjectId has an internal counter
assertThat(target.get("dateAsObjectId", ObjectId.class).getTimestamp())
.isEqualTo(new ObjectId(source.dateAsObjectId).getTimestamp());
}
@Test // DATAMONGO-2328
public void readsObjectIdAsDateWhenAnnotatedWithFieldTargetType() {
ObjectId reference = new ObjectId();
WithExplicitTargetTypes target = converter.read(WithExplicitTargetTypes.class,
new org.bson.Document("dateAsObjectId", reference));
assertThat(target.dateAsObjectId).isEqualTo(new Date(reference.getTimestamp()));
}
static class GenericType<T> {
T content;
}
@@ -1987,9 +2086,7 @@ public class MappingMongoConverterUnitTests {
},
SECOND {
@Override
void method() {
}
void method() {}
};
abstract void method();
@@ -2416,7 +2513,20 @@ public class MappingMongoConverterUnitTests {
@Field(targetType = FieldType.SCRIPT) //
List<String> scripts;
@Field(targetType = FieldType.DECIMAL128) BigDecimal bigDecimal;
@Field(targetType = FieldType.DECIMAL128) //
BigDecimal bigDecimal;
@Field(targetType = FieldType.INT64) //
Date dateAsLong;
@Field(targetType = FieldType.DATE_TIME) //
Long longAsDate;
@Field(targetType = FieldType.BOOLEAN) //
String stringAsBoolean;
@Field(targetType = FieldType.OBJECT_ID) //
Date dateAsObjectId;
}
}