Spring -Data MongoDB问题,字段是一个接口

我正在使用Spring-Data for MongoDB:

版本信息 - org.mongodb.mongo-java-driver version 2.10.1, org.springframework.data.spring-data-mongodb version 1.2.1.RELEASE.

我有一个类似于这里定义的案例,即(抱歉格式...):

我刚刚开始用spring-data-mongodb在Java中开发一些应用程序,并遇到了一些我无法解决的问题:

我有几个像这样的文档豆:

@Document(collection="myBeanBar")
public class BarImpl implements Bar {
    String id;
    Foo foo;
    // More fields and methods ... 
}

@Document
public class FooImpl implements Foo {
    String id;
    String someField;
    // some more fields and methods ...
} 

我有一个存储库类,其中包含一个方法,该方法只是调用类似于以下内容的查找:

public List<? extends Bar> findByFooField(final String fieldValue) {
    Query query = Query.query(Criteria.where("foo.someField").is(fieldValue));
    return getMongoOperations().find(query, BarImpl.class);
} 

保存一个 Bar 工作得很好,它会将其与 Foo 和 Bar 的“_class”属性一起保存在 mongo 中。但是,在 Foo 中查找某个属性会引发如下异常:

Exception in thread "main" java.lang.IllegalArgumentException: No
property someField found on test.Foo!
    at org.springframework.data.mapping.context.AbstractMappingContext.getPersistentPropertyPath(AbstractMappingContext.java:225)
    at org.springframework.data.mongodb.core.convert.QueryMapper.getPath(QueryMapper.java:202)
    at org.springframework.data.mongodb.core.convert.QueryMapper.getTargetProperty(QueryMapper.java:190)
    at org.springframework.data.mongodb.core.convert.QueryMapper.getMappedObject(QueryMapper.java:86)
    at org.springframework.data.mongodb.core.MongoTemplate.doFind(MongoTemplate.java:1336)
    at org.springframework.data.mongodb.core.MongoTemplate.doFind(MongoTemplate.java:1322)
    at org.springframework.data.mongodb.core.MongoTemplate.find(MongoTemplate.java:495)
    at org.springframework.data.mongodb.core.MongoTemplate.find(MongoTemplate.java:486)

给出的解决方案是在抽象类上使用@TypeAlias注释,它告诉框架使用特定的实现(在本例中为FooImpl)。

在我的情况下,我有接口成员,而不是抽象成员:

@Document(collection="myBeanBar")
public class BarImpl implements Bar {
    String id;
    IFoo foo;
    // More fields and methods ...
}

我非常不愿意在接口IFoo上放置一个注释来给出默认实现,而是我想告诉框架这个字段在实现BarImpl类的上下文中的默认实现是什么,类似于@JsonTypeInfo:

@Document(collection="myBeanBar") 
public class BarImpl implements Bar {
    String id;    

    @JsonTypeInfo(use = Id.CLASS, defaultImpl = FooImpl.class)
    IFoo foo; 

    // More fields and methods ... 
}

我找到了这个答案,它或多或少地说要避免使用接口。但我很高兴知道如果没有更好的选择。

有什么想法吗?

谢谢!


答案 1

我的问题与问题类似,但引发的异常有点不同:

Could not instantiate bean class [class name]: Specified class is an interface

当我的 DB 类的某个字段声明为接口时,会发生这种情况。保存此字段很好,但是从MongoDB读取它时会引发异常。最后,我找到了利用.org.springframework.core.convert.converter.Converter

两个步骤要做,1。构造一个实现 ;2. 在 servlet 上下文中注册转换器。是的,您不必修改任何现有代码,例如添加注释。Converter

下面是我的模型类,其中字段是一个接口:Data

@Document(collection="record")
public class Record {
    @Id
    private String id;

    // Data is an interface
    private Data data;

    // And some other fields and setter/getter methods of them
}

转换器:

@ReadingConverter
public class DataReadConverter implements Converter<DBObject, Data> {
    @Override
    public Data convert(DBObject source) {
        // Your implementation to parse the DBObject,
        // this object can be BasicDBObject or BasicDBList,
        // and return an object instance that implements Data.

        return null;
    }
}

最后要做的是注册转换器,我的配置是xml:

<mongo:mongo id="mongo" />

<mongo:db-factory mongo-ref="mongo" dbname="example" />

<mongo:mapping-converter>
    <mongo:custom-converters>
        <mongo:converter>
            <beans:bean class="com.example.DataReadConverter" />
        </mongo:converter>
    </mongo:custom-converters>
</mongo:mapping-converter>

<beans:bean id="mongoTemplate" class="org.springframework.data.mongodb.core.MongoTemplate">
    <beans:constructor-arg name="mongoDbFactory" ref="mongoDbFactory" />
    <beans:constructor-arg name="mongoConverter" ref="mappingConverter" />
</beans:bean>

部署应用程序,然后重试。它应该在接口字段上正确解析来自MongoDB的DBObject。

我的Spring MongoDB应用程序的版本是:spring-*-4.1.0和spring-data-mongodb-1.6.0。


答案 2

我收到与@victor-wong相同的错误消息

Could not instantiate bean class [class name]: Specified class is an interface

下面的代码解决了 和Spring Boot 2.3.2spring-data-mongodb 3.0.2

转换器:

import org.bson.Document;
import org.springframework.core.convert.converter.Converter;
import org.springframework.data.convert.ReadingConverter;

@ReadingConverter
public class DataReadConverter implements Converter<Document, Data> {

    @Override
    public Data convert(Document source) {

        return new DataImpl(source.get("key"));
    }
}

最后要做的是注册转换器

    @Bean
    public MongoCustomConversions customConversions() {
        return new MongoCustomConversions(
                List.of(
                        new DataReadConverter()
                )
        );
    }

可在此处找到更多信息:https://jira.spring.io/browse/DATAMONGO-2391