如何使用Spring-Data-MongoDb调整Guava Optional
(或更高版本的JDK8 Optionals)的映射?
作为一个例子,下面的类应该像下面的json一样映射。
@Data
public class Test
{
Optional<String> stringOptionalNull = null;
Optional<String> stringOptionalAbsent = Optional.absent();
Optional<String> stringOptionalPresent = Optional.of("ExampleValue");
}
Json(注意:Null和缺席案件的处理方式相同):
{
"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数据mongo不会触发null对象的自定义转换。 这是因为: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
答案 0 :(得分:0)
我不使用Spring,因此我不知道这是否适合您,但尝试让您的setter“正常”工作并将您的getter转换为:
public Optional<String> getFoo()
{
return Optional.fromNullable(foo);
}
如果foo
为null
,则Optional.absent()
将为.isPresent()
返回false
。
在Java 8中(来自Guava的“被盗”Optional
)API有点不同;它不是Optional.absent()
而是Optional.empty()
,而.fromNullable()
已成为.ofNullable()
。