2016-08-19 81 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()); 
} 
相關問題