Как настроить сопоставление Guava Optional
s (или более поздних опций JDK8) с помощью Spring-Data-MongoDb?
В качестве примера следующий класс должен быть сопоставлен как json ниже.
@Data
public class Test
{
Optional<String> stringOptionalNull = null;
Optional<String> stringOptionalAbsent = Optional.absent();
Optional<String> stringOptionalPresent = Optional.of("ExampleValue");
}
Json (Примечание. Нулевой и отсутствующий случаи обрабатываются одинаково):
{
"stringOptionalPresent" : "ExampleValue"
}
Когда они снова преобразуются обратно в java, null
и absent
должны быть преобразованы в Optional.absent()
.
Из Spring Data MongoDB Docs Я читал, что org.springframework...Converter
- это то, что нужно. Но с помощью API мне не удалось правильно обработать null
случаев.
Это полный тестовый пример для воспроизведения проблемы. Он передает null
и проверяет, что загруженный объект содержит только Optional.absent()
.
public class OptionalMongoDbTest
{
@Data
@AllArgsConstructor
static class ClassWithOptionals
{
private final Optional<String> stringOptionalNull;
private final Optional<String> stringOptionalPresent;
private final Optional<String> stringOptionalAbsent;
}
public static class OptionalToStringConverter<T> implements Converter<Optional<T>, String>
{
@Override
public String convert(final Optional<T> arg0)
{
return arg0.isPresent() ? arg0.get().toString() : null;
}
}
public static class StringToOptionalConverter implements Converter<String, Optional<String>>
{
@Override
public Optional<String> convert(final String arg0)
{
return Optional.fromNullable(arg0);
}
}
@Test
public void persisted_object_should_be_equal() throws Exception
{
// Setup Mongodb connection
final SimpleMongoDbFactory mongoDbFactory = new SimpleMongoDbFactory(new Mongo(), "test");
final MappingMongoConverter converter = new MappingMongoConverter(mongoDbFactory, new MongoMappingContext());
// Register Custom Converter
converter.setCustomConversions(new CustomConversions(Arrays.asList(new OptionalToStringConverter(), new StringToOptionalConverter())));
converter.afterPropertiesSet();
final MongoTemplate mongoTemplate = new MongoTemplate(mongoDbFactory, converter);
mongoTemplate.setWriteConcern(WriteConcern.SAFE);
// Test the mapping
mongoTemplate.dropCollection(ClassWithOptionals.class);
final ClassWithOptionals objectToSave = new ClassWithOptionals(null, Optional.of("ExampleValue"), Optional.<String> absent());
mongoTemplate.save(objectToSave);
final ClassWithOptionals objectFromMongo = mongoTemplate.findAll(ClassWithOptionals.class).get(0);
// TODO: That test fails because there are null values comming from the databases
assertThat(objectFromMongo, is(new ClassWithOptionals(Optional.<String> absent(), Optional.of("ExampleValue"), Optional.<String> absent())));
}
}
Кроме того, json, сгенерированный этим тестом, выглядит так:
{
"_id" : ObjectId("5343d8a5e4b0215d78a322d0"),
"stringOptionalPresent" : "ExampleValue",
"stringOptionalAbsent" : null // this line should be removed.
}
Изменить
Я думаю, что это невозможно, потому что Spring Data Mongo не запускает пользовательские преобразования для нулевых объектов. Это из-за этого: https://github.com/spring-projects/spring-data-mongodb/blob/master/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/MappingMongoConverter.java#L1037-L1041
Optional
– избежать нулевых значений! Зачем вообще давать возможность иметь nullOptional
? - person fge   schedule 03.04.2014Optional
с помощью API MongoDB? - person fge   schedule 04.04.2014Optional.absent()
? Я не говорю, что это невыполнимо, но вам придется указать, что вы хотите. Кроме того, другим вариантом было бы, чтобы геттер возвращал толькоOptional
; сеттер будет работать нормально. - person fge   schedule 04.04.2014