我对Spring还是很陌生,但是我想尝试一下这个项目。 我有一个非常复杂的文档填充的MongoDB数据库。我想使用Spring数据Mongo查询(没有其他CRUD操作)数据库。
我已经使用POJO描述了我的文档实体,但是其中一些是抽象的(请参阅GeometryGeoJSON
用于接受所有类型的GeoJson几何图形,或者可以是Contact
的{{1}}或Person
。下面提供了指向GitHub存储库的链接。
使用该实体定义进行测试后,会抛出Organisation
,这很公平,因为在这些抽象类中未定义任何Contructor。
这里是GitHub repository,以备不时之需。
我对这一切感到有点迷茫,但我会更仔细地阅读文档。
您将如何面对这个问题?
答案 0 :(得分:0)
我会回答我自己的问题。如评论中所述,解决方案是使用Converter
。
这是我打算通过班级模型实现的示例:
Contact
可以是Person
或Organisation
。
如果您正在使用spring-data-mongodb MongoRepository根据您的实体模型在数据库中写入数据,则会将_class
字段添加到文档根目录和复杂的属性类型({{ 3}})。该字段存储Java类的完全限定名称,在从MongoDb文档映射到Spring数据模型时,它可以消除歧义。
如果您的应用只是从数据库中读取文档(没有_class
字段),则需要告诉Spring数据在映射Contact
时要实例化哪个类。 Spring-data允许您使用Converter
自定义默认类型映射行为。使用显式Converter
see this section。您需要显式映射整个类。这是我的 ContactReadConverter 的示例:
@ReadingConverter
public class ContactReadConverter implements Converter<Document, Contact> {
@Override
public Contact convert(Document source) {
if (source.get("firstName") == null) {
Organisation organisation = new Organisation();
I18n name = new I18n();
name.setEn(source.get("name", Document.class).get("en", String.class));
name.setFr(source.get("name", Document.class).get("fr", String.class));
organisation.setName(name);
organisation.setAcronym(source.get("acronym", String.class));
organisation.setRole(source.get("role", String.class));
return organisation;
}
Person person = new Person();
person.setFirstName(source.get("firstName", String.class));
person.setLastName(source.get("lastName", String.class));
person.setRole(source.get("role", String.class));
person.setEmail(source.get("email", String.class));
person.setOrcId(source.get("orcId", String.class));
if (source.get("organisation") != null) {
Document sourceOrg = source.get("organisation", Document.class);
Organisation organisation = new Organisation();
organisation.setAcronym(sourceOrg.get("acronym", String.class));
organisation.setRole(sourceOrg.get("role", String.class));
if (sourceOrg.get("name") != null) {
I18n name = new I18n();
name.setFr(sourceOrg.get("name", Document.class).get("fr", String.class));
name.setEn(sourceOrg.get("name", Document.class).get("en", String.class));
organisation.setName(name);
}
person.setOrganisation(organisation);
}
return person;
}
}
然后,需要注册新定义的转换器:
@Configuration
public class DataportalApplicationConfig extends AbstractMongoConfiguration {
@Value("${spring.data.mongodb.uri}")
private String uri;
@Value("${spring.data.mongodb.database}")
private String database;
@Override
public MongoClient mongoClient() {
return new MongoClient(new MongoClientURI(uri));
}
@Override
protected String getDatabaseName() {
return database;
}
@Bean
@Override
public MongoCustomConversions customConversions() {
List<Converter<?, ?>> converterList = new ArrayList<>();
converterList.add(new ContactReadConverter());
return new MongoCustomConversions(converterList);
}
}
希望有帮助。