繁体   English   中英

Spring Data Mongo-如何映射继承的POJO实体?

[英]Spring Data Mongo - How to map inherited POJO entities?

我刚接触Spring,但是想尝试一下这个项目。 我有一个非常复杂的文档填充的MongoDB数据库。 我想使用Spring数据Mongo查询(没有其他CRUD操作)数据库。

我已经使用POJO描述了我的文档实体,但是其中一些是抽象的(请参阅GeometryGeoJSON用于接受所有类型的GeoJson几何或可以是PersonOrganisation Contact 。下面提供了指向GitHub存储库的链接)。

使用该实体定义进行测试后,会抛出java.lang.InstantiationError ,这很公平,因为在这些抽象类中未定义任何Contructor。

如果需要查看,这里是GitHub存储库

我对这一切感到有些迷茫,但是我会更仔细地阅读文档。

您将如何面对这个问题?

我会回答我自己的问题。 如评论中所述,解决方案是使用Converter

这是我打算通过班级模型实现的示例:

在此处输入图片说明

Contact可以是PersonOrganisation

如果您使用spring-data-mongodb MongoRepository根据您的实体模型在数据库中写入数据,则_class字段将添加到文档根目录和复杂的属性类型( 请参阅本节 )。 该字段存储Java类的完全限定名称,在从MongoDb文档映射到Spring数据模型时,它可以消除歧义。

如果您的应用只是从数据库中读取文档(没有_class字段),则需要在映射Contact时告诉Spring数据要实例化哪个类。 Spring-data允许您使用Converter自定义默认类型映射行为。 使用显式Converter 覆盖该类的默认映射 您需要显式映射整个类。 这是我的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);
    }
}

希望能帮助到你。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM