以编程方式设置 MongoDb 转换器

Posted

技术标签:

【中文标题】以编程方式设置 MongoDb 转换器【英文标题】:Set MongoDb converter programmatically 【发布时间】:2012-11-26 16:05:37 【问题描述】:

我正在尝试使用带有 spring-data-mongodb 的自定义转换器。我想以编程方式创建它,但出现以下错误:

org.springframework.core.convert.ConverterNotFoundException: No converter found capable of     converting from type org.joda.time.LocalDate to type java.lang.String
at org.springframework.core.convert.support.GenericConversionService.handleConverterNotFound(GenericConversionService.java:475)
at org.springframework.core.convert.support.GenericConversionService.convert(GenericConversionService.java:175)
at org.springframework.core.convert.support.GenericConversionService.convert(GenericConversionService.java:154)
....
....

下面是失败的代码sn-p:

    Mongo mongo = new Mongo();
    MongoDbFactory mongoDbFactory = new SimpleMongoDbFactory(mongo, "database");

    List<Converter> converters = new ArrayList<>();
    converters.add(new LocalDateWriteConverter());
    converters.add(new LocalDateReadConverter());
    CustomConversions customConversions = new CustomConversions(converters);

    MappingContext mappingContext = new SimpleMongoMappingContext();
    MappingMongoConverter mappingMongoConverter = new MappingMongoConverter(mongoDbFactory, mappingContext);
    mappingMongoConverter.setCustomConversions(customConversions);

    MongoTemplate mongoTemplate = new MongoTemplate(mongoDbFactory, mappingMongoConverter);

    MongoDbEvent mongoEvent = new MongoDbEvent(new LocalDate(2012, 12, 8));
    mongoTemplate.insert(mongoEvent);

这是我的转换器类:

class LocalDateReadConverter implements Converter<String, LocalDate> 
    @Override
    public LocalDate convert(String s) 
        // Conversion code omitted.
    


class LocalDateWriteConverter implements Converter<LocalDate, String> 

    @Override
    public String convert(LocalDate localDate) 
        // Conversion code omitted.
    

我试图坚持的课程如下所示:

import org.joda.time.LocalDate;

public class MongoDbEvent 

    private String id;
    private LocalDate date;

    public MongoDbEvent(LocalDate date) 
        this.date = date;
    

    public String getId() 
        return id;
    

    public LocalDate getDate() 
        return date;
    

    @Override
    public String toString() 
        return "MongoDbEvent" +
                "id='" + id + '\'' +
                ", date=" + date +
                '';
        

【问题讨论】:

【参考方案1】:

对我来说,它是将我的转换器注册为读者而不是作家。要解决此问题,您需要将 @WritingConverter 注释添加到转换器类

@Component
@WritingConverter
public class NoteWriterConverter implements Converter<Note, DBObject> 

@Override
public DBObject convert(Note source) 
    DBObject obj = new BasicDBObject();

    obj.put("title", source.getTitle());
    obj.put("reviewDate", source.getReviewDate());

    obj.removeField("_class");
    return obj;
    

【讨论】:

【参考方案2】:

由于org.springframework.data:spring-data-commons:1.13.3.RELEASE,以下是如何使用自定义转换器以编程方式创建MongoTemplate

public MongoTemplate mongoTemplate(String mongoUri) throws Exception 
    MongoDbFactory factory = new SimpleMongoDbFactory(new MongoClientURI(mongoUri));
    CustomConversions conversions = new CustomConversions(
            Arrays.asList(new FooWriteConverter(), new FooReadConverter()));
    MongoMappingContext mappingContext = new MongoMappingContext();
    DbRefResolver dbRefResolver = new DefaultDbRefResolver(factory);
    MappingMongoConverter mongoConverter = new MappingMongoConverter(dbRefResolver, mappingContext);
    mongoConverter.setCustomConversions(conversions);
    mongoConverter.afterPropertiesSet();
    return new MongoTemplate(factory, mongoConverter);

转换器(省略实现)

class FooWriteConverter implements Converter<Foo, DBObject>  ... 
class FooReadConverter implements Converter<DBObject, Foo>  ... 

【讨论】:

【参考方案3】:

这里详细描述了如何使用自定义转换器自定义mongo:

http://docs.spring.io/spring-data/mongodb/docs/current/reference/html/#mapping-configuration

我注入了默认配置值,因此我可以从 application.properties 配置设置中受益。

  @Configuration
  public class MongoConfiguration extends AbstractMongoConfiguration 
    @Value("$spring.data.mongodb.database:test")
    String database;

    @Value("$spring.data.mongodb.host:localhost:$spring.data.mongodb.port:27017")
    String host;

    @Override
    protected String getDatabaseName() 
      return database;
    

    @Override
    public Mongo mongo() throws Exception 
      return new MongoClient(host);
    

    @Bean
    @Override
    public CustomConversions customConversions() 
      List<Converter<?, ?>> converterList = new ArrayList<Converter<?, ?>>();
      converterList.add(new MongoColorWriter());
      converterList.add(new MongoColorReader());
      return new CustomConversions(converterList);
    
  

【讨论】:

分享的链接很有帮助。【参考方案4】:

只是提个醒。我在spring-data-mongodb 1.5.1.RELEASEusing Java Configuration 上遇到了这个问题。由于某些课程发生了变化,我将发布我的解决方案。

在带有@Configuration注解的配置类中添加以下定义:

@Bean
public Mongo mongo() throws Exception 
    MongoPropertiesResolver resolver = mongoResolver();
    return new MongoClient(resolver.getUrl());


@Bean
public MongoDbFactory mongoDbFactory() throws Exception 
    return new SimpleMongoDbFactory(mongo(), "database");


@Bean
public MongoTemplate mongoTemplate() throws Exception 
    return new MongoTemplate(mongoDbFactory(), mongoConverter());


@Bean
public CustomConversions customConversions() 
    List<Converter<?, ?>> converters = new ArrayList<Converter<?, ?>>();
    converters.add(new TimeZoneReadConverter());
    converters.add(new TimeZoneReadConverter());
    return new CustomConversions(converters);


@Bean
public MappingMongoConverter mongoConverter() throws Exception 
    MongoMappingContext mappingContext = new MongoMappingContext();
    DbRefResolver dbRefResolver = new DefaultDbRefResolver(mongoDbFactory());
    MappingMongoConverter mongoConverter = new MappingMongoConverter(dbRefResolver, mappingContext);
    mongoConverter.setCustomConversions(customConversions());
    return mongoConverter;

【讨论】:

构造函数 SimpleMongoDbFactory(Mongo, String) 已弃用 - 我使用的是 Spring Boot 1.3.2 感谢代码示例,这有助于我在尝试使用 Fongo 组合一些单元测试时设置一些自定义转换器。【参考方案5】:

随着 java.time 包在 java 8 中的引入,我在使用新包中的新 LocalDate 和 LocalDateTime 类时遇到了类似的问题。 我就是这样解决的:

我为所有这 4 个转换选项编写了一个转换器:

DateToLocalDateTime 转换器 DateToLocalDateConverter Lo​​calDateTimeToDateConverter Lo​​calDateToDateConverter

这是一个例子

public class DateToLocalDateTimeConverter implements Converter<Date, LocalDateTime> 

    @Override 
    public LocalDateTime convert(Date source)  
        return source == null ? null : LocalDateTime.ofInstant(source.toInstant(), ZoneId.systemDefault()); 
    

然后通过将它包含在 mongodb 连接的 xml 配置中,我能够使用 mongodb 在 java 8 日期中工作(记得添加所有转换器):

<mongo:mapping-converter>
    <mongo:custom-converters>
        <mongo:converter>
            <bean class="package.DateToLocalDateTimeConverter" />
        </mongo:converter>
    </mongo:custom-converters>
</mongo:mapping-converter>

【讨论】:

【参考方案6】:

这个答案对于OP来说可能有点晚了,但是我今天遇到了同样的问题并找到了解决方案......

要以编程方式进行设置,您需要在使用前调用MongoMappingConverter.afterPropertiesSet()。我通过阅读MongoTemplate.getDefaultMongoConverter(MongoDbFactory) 的代码意识到了这一点。

这是一个例子:

MappingMongoConverter converter = new MappingMongoConverter(mongoDbFactory, context);
converter.setTypeMapper(mapper);
converter.setCustomConversions(new CustomConversions(
        Arrays.asList(
                new TimeZoneReadConverter(),
                new TimeZoneWriteConverter()
        )
));
converter.afterPropertiesSet();
MongoTemplate template = new MongoTemplate(mongoDbFactory, converter);

【讨论】:

非常感谢!正如我在 spring-data 的单元测试中看到的 .afterPropertiesSet(); 一样,我没有给予足够的重视...... 救世主!! :) 谢谢你,虽然我仍然需要了解文档。

以上是关于以编程方式设置 MongoDb 转换器的主要内容,如果未能解决你的问题,请参考以下文章

以编程方式将 iPhone MOV 转换为 Mp4 视频

在哪里以编程方式设置 TableViewController 的 UIBarButtonItem 和单元格“segue”

Selenium - 以编程方式将 html 转换为 junit

以编程方式将 fbx 转换为 scn

使用 .NET 以编程方式运行流分析转换查询

UISegmentedControl:以编程方式设置索引?