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)
....
....
以下は、失敗したコードスニペットです。
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 +
'}';
}
}
この答えは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-mongodb 1.5.1.RELEASE
using 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;
}
カスタムコンバーターで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);
}
}
Java 8にJava.timeパッケージが導入されたため、新しいパッケージの新しいLocalDateクラスとLocalDateTimeクラスを使用して同様の問題に遭遇しました。次のようにして解決しました:
これらの4つの変換オプションすべてに対応するコンバーターを作成しました。
ここに例があります
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構成に含めることで、Java 8つの日付でmongodbを使用して作業できました(すべてのコンバーターを追加することを忘れないでください)。
<mongo:mapping-converter>
<mongo:custom-converters>
<mongo:converter>
<bean class="package.DateToLocalDateTimeConverter" />
</mongo:converter>
</mongo:custom-converters>
</mongo:mapping-converter>
私にとっては、ライターをライターではなくリーダーとして登録することでした。これを修正するには、@ 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;
}
}
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> { ... }