使用Spring-Data在MongoDB中保存并加载Guava可选<! - ? - >

时间:2014-04-03 13:18:41

标签: java mongodb spring-data spring-data-mongodb

如何使用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时,nullabsent应该转换为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

1 个答案:

答案 0 :(得分:0)

我不使用Spring,因此我不知道这是否适合您,但尝试让您的setter“正常”工作并将您的getter转换为:

public Optional<String> getFoo()
{
    return Optional.fromNullable(foo);
}

如果foonull,则Optional.absent()将为.isPresent()返回false

在Java 8中(来自Guava的“被盗”Optional)API有点不同;它不是Optional.absent()而是Optional.empty(),而.fromNullable()已成为.ofNullable()