Spring Data Mongo-如何映射继承的POJO实体? [英] Spring Data Mongo - How to map inherited POJO entities?
问题描述
我对Spring还是很陌生,但是我想尝试一下这个项目. 我有一个非常复杂的文档填充的MongoDB数据库.我想使用Spring数据Mongo来查询(没有其他CRUD操作)数据库.
I'm fairly new to Spring but I want to give it a try on this project. I have a MongoDB database populated with quite complexe documents. I want to use Spring data Mongo to query (no other CRUD operations) the database.
我已经使用POJO描述了我的文档实体,但是其中一些是抽象的(请参阅GeometryGeoJSON
用于接受所有类型的GeoJson几何或Contact
,可以是Person
或Organisation
.)下面提供了到GitHub存储库的链接).
I already described my document entity using POJOs but some of them are abstract (see GeometryGeoJSON
is used to accept all type of GeoJson geometry, or Contact
that can be a Person
or an Organisation
. The link to the GitHub repo is provided below).
使用该实体定义进行测试后,会抛出java.lang.InstantiationError
,这很公平,因为在这些抽象类中未定义任何Contructor.
Having a test with that entity definition, a java.lang.InstantiationError
is thrown which fair since no Contructor are defined in those abstract classes.
这里是 GitHub存储库,以备不时之需.
Here is GitHub repository in case you need to have a look.
我对这一切感到有些迷茫,但是我会更仔细地阅读文档.
I feel a bit lost with all this but I'll have a more careful look at the documentation.
您将如何面对这个问题?
How would you face this issue ?
推荐答案
我将回答我自己的问题.如评论中所述,解决方案是使用Converter
.
I'll answer my own question. As mentioned in the comments, the solution is to use Converter
.
这是我打算通过班级模型实现的示例:
Here is an example of what I intended to achieve with my class model :
A Contact
可以是Person
或Organisation
.
如果您使用的是spring-data-mongodb 参见此部分).该字段存储Java类的完全限定名称,在从MongoDb文档映射到Spring数据模型时,它可以消除歧义.
If you are using spring-data-mongodb MongoRepository to write data in your database according to your entity model, a _class
field will be added to document roots and to complex property types (see this section). This fields store the fully qualified name of the Java class and it allows disambiguation when mapping from MongoDb Document to Spring data model.
如果您的应用只是从数据库中读取文档(没有_class
字段),则需要告诉Spring数据在映射Contact
时要实例化哪个类. Spring-data允许您使用Converter
自定义默认类型映射行为.使用显式Converter
If your app just read document from the database (no _class
fields), you need to tell Spring data which class to instantiate when mapping a Contact
. Spring-data allows you to customize default type mapping behaviour using Converter
. Using explicit Converter
override default mapping for the class. you need to explicitly map your entire class. Here is an example of my 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;
}
}
然后,需要注册新定义的转换器:
Then, newly defined converters need to be registered:
@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);
}
}
希望有帮助.
这篇关于Spring Data Mongo-如何映射继承的POJO实体?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!