[英]Save and load Guava Optional<?>s in MongoDB using Spring-Data
How to tune the mapping of the Guava Optional
s (or later the JDK8 Optionals) with Spring-Data-MongoDb? 如何使用Spring-Data-MongoDb调整Guava
Optional
s(或更高版本的JDK8 Optionals)的映射?
As an example the following class should be mapped like the json below. 作为示例,下面的类应该像下面的json一样映射。
@Data
public class Test
{
Optional<String> stringOptionalNull = null;
Optional<String> stringOptionalAbsent = Optional.absent();
Optional<String> stringOptionalPresent = Optional.of("ExampleValue");
}
Json (Note: The Null and absent cases are treated in the same manner): Json(注意:Null和Absent案例的处理方式相同):
{
"stringOptionalPresent" : "ExampleValue"
}
When they are converted back to java again, the null
and absent
should be translated to Optional.absent()
. 当它们再次转换回java时,
null
和absent
应该被转换为Optional.absent()
。
From the Spring Data MongoDB Docs I read that the org.springframework...Converter
s are the way to go. 从Spring Data MongoDB Docs我读到
org.springframework...Converter
是org.springframework...Converter
的方法。 But with the API I was not able to treat the null
cases correct. 但是使用API我无法正确处理
null
案例。
The is a complete testcase to reproduce the problem. 这是一个完整的测试用例来重现问题。 It hands in a
null
and tests that the loaded object contains only Optional.absent()
. 它交出一个
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())));
}
}
Furthermore the json generated by this test looks like this: 此外,此测试生成的json如下所示:
{
"_id" : ObjectId("5343d8a5e4b0215d78a322d0"),
"stringOptionalPresent" : "ExampleValue",
"stringOptionalAbsent" : null // this line should be removed.
}
Edit 编辑
I think that is not possible because spring data mongo doesn't trigger custom conversions on null objects. 我认为这是不可能的,因为spring数据mongo不会触发null对象的自定义转换。 That is because of this: 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
这是因为: https : //github.com/spring-projects/spring-data-mongodb/blob/master/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/转换/ MappingMongoConverter.java#L1037-L1041
I don't use Spring so I don't know whether this will work for you but try and make your setter work "normally" and transform your getter to this: 我不使用Spring,所以我不知道这是否适合你,但尝试让你的setter“正常”工作并将你的getter转换为:
public Optional<String> getFoo()
{
return Optional.fromNullable(foo);
}
If foo
is null
, it will be an Optional.absent()
for which .isPresent()
will return false
. 如果
foo
为null
,则它将是Optional.absent()
,其中.isPresent()
将返回false
。
In Java 8 (which has "stolen" Optional
from Guava) the API is a little different; 在Java 8中(其中“偷了”来自Guava的
Optional
),API有点不同; it is not Optional.absent()
but Optional.empty()
, and .fromNullable()
has become .ofNullable()
. 它不是
Optional.absent()
而是Optional.empty()
,而.fromNullable()
已成为.ofNullable()
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.