Spring Data Mongo-如何映射继承的POJO实体? [英] Spring Data Mongo - How to map inherited POJO entities?

查看:604
本文介绍了Spring Data Mongo-如何映射继承的POJO实体?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我对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,可以是PersonOrganisation.)下面提供了到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可以是PersonOrganisation.

如果您使用的是spring-data-mongodb

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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆