2016-08-19 42 views
0

我在Spring Data MongoDB中使用Spring Cloud Brixton.SR4Spring Mongodb - 无法为java.time.Period编写自定义转换器

我有一个非常简单的实体:

@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吗?

编辑

这似乎是一个注册问题。当我调试代码时,在MappingMongoConverter中使用的CustomConversion对象与我创建的对象不同。而且它不具有创建

回答

1

确定这是愚蠢至极...

我也创造我自己的MongoTemplate定制转换器:

@Bean 
public MongoTemplate mongoTemplate() throws Exception { 
    return new MongoTemplate(mongoDbFactory()); 
} 

这基本上忽略了我的自定义转换器。修复它:

@Bean 
public MongoTemplate mongoTemplate() throws Exception { 
    return new MongoTemplate(mongoDbFactory(), mappingMongoConverter()); 
} 
相关问题