我正在使用Spring Cloud Brixton.SR4
和Spring Data MongoDB。
我有一个非常简单的实体:
@Document
public class Foo{
private Period period;
//getter & setter
}
由于java.time.Period
不支持jsr310
我正在创建自定义转换器:
class Converters {
@Component
@WritingConverter
static class PeriodToStringConverter implements Converter<Period, String> {
@Override
public String convert(Period period) {
return period.toString();
}
}
@ReadingConverter
@Component
static class StringToPeriodConverter implements Converter<String, Period> {
@Override
public Period convert(String s) {
return Period.parse(s);
}
}
现在我在扩展AbstractMongoConfiguration
的配置类中注册它们:
@Bean
@Override
public MappingMongoConverter mappingMongoConverter() throws Exception {
DbRefResolver dbRefResolver = new DefaultDbRefResolver(mongoDbFactory());
MappingMongoConverter converter = new MappingMongoConverter(dbRefResolver, mongoMappingContext());
final CustomConversions conversions = customConversions();
log.info("hasCustomWriteTarget(Period.class): " + conversions.hasCustomWriteTarget(Period.class));
log.info("hasCustomWriteTarget(Period.class, String.class): " + conversions.hasCustomWriteTarget(Period.class, String.class));
log.info("hasCustomReadTarget(String.class, Period.class): " + conversions.hasCustomReadTarget(String.class, Period.class));
converter.setCustomConversions(conversions);
converter.afterPropertiesSet(); //probably not needed, trying out of despair
return converter;
}
@Bean
@Override
public CustomConversions customConversions() {
List<Converter> converters = new ArrayList<>();
converters.add(new Converters.PeriodToStringConverter());
converters.add(new Converters.StringToPeriodConverter());
return new CustomConversions(converters);
}
当我启动我的应用程序时,我会在日志中看到:
hasCustomWriteTarget(Period.class): true
hasCustomWriteTarget(Period.class, String.class): true
hasCustomReadTarget(String.class, Period.class): true
现在我创建一个新的Foo
并将其保存到我的存储库:
Foo foo = new Foo();
foo.setPeriod(Period.of(2, 0, 1));
fooRepository.save(foo);
现在发生了奇怪的事情:
在Mongodb中我看到:
{
"_id": ObjectId("xxxx"),
"period": {
"years" : 0,
"months" : 2,
"days" : 1
}
}
所以这已经是错的了。它应保存为String
当我尝试用Java读取对象时,我得到:
org.springframework.data.mapping.model.MappingException: No property null found on entity class java.time.Period to bind constructor parameter to!
我调试了MappingMongoConverter
中的代码:
if (conversions.hasCustomReadTarget(dbo.getClass(), rawType)) {
return conversionService.convert(dbo, rawType);
}
因为我的对象没有以字符串形式存储,dbo
变量实际上是BasicDbObject
因此我没有转换器。
知道为什么我的写入转换器没有被用来保留Period
?
我的课程路径上有jackson-datatype-jdk8
,这可能是问题吗?杰克逊是否会参与继续留在Mongodb?
修改
这似乎是一个注册问题。调试代码时,CustomConversion
中使用的MappingMongoConverter
对象与我创建的对象不同。它没有我创建的自定义转换器
答案 0 :(得分:1)
我还创建了自己的MongoTemplate
:
@Bean
public MongoTemplate mongoTemplate() throws Exception {
return new MongoTemplate(mongoDbFactory());
}
这基本上忽略了我的自定义转换器。解决它:
@Bean
public MongoTemplate mongoTemplate() throws Exception {
return new MongoTemplate(mongoDbFactory(), mappingMongoConverter());
}