我正在使用Spring-Data for MongoDB:
版本信息 - org.mongodb.mongo-java-driver版本2.10.1, org.springframework.data.spring-data-mongodb version 1.2.1.RELEASE。
我的案例类似于here中定义的案例,(对不起格式化......):
我刚开始使用spring-data-mongodb开发一些Java应用程序,并遇到了一些我无法解决的问题:
我有几个像这样的文档bean:
@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);
}
保存栏工作得很好,它会将它与mongo一起保存 Foo和Bar的“_class”属性。然而,由一些人发现 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 ...
}
我找到了this answer,或多或少说要避免使用接口。但我很高兴知道是否有更好的选择。
有什么想法吗?
谢谢!
答案 0 :(得分:7)
我的问题类似于问题,但抛出的异常有点不同:
Could not instantiate bean class [class name]: Specified class is an interface
当我的DB类的一个字段被声明为接口时会发生这种情况。保存此字段很好,但从MongoDB读取它时会抛出异常。最后,我找到了使用org.springframework.core.convert.converter.Converter
的解决方案。
要做的两个步骤,1。构建一个实现Converter
的类; 2.在servlet上下文中注册转换器。是的,您不必修改任何现有代码,例如添加注释。
下面是我的模型类,其中字段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。
答案 1 :(得分:0)
将接口定义为数据对象中的字段是非常糟糕的。
接口意味着某些对象可能做某事,但不提供有关字段的任何信息。你真的需要使用接口吗?你能避免这个吗?即使使用抽象类定义也会更好。
P.S。当然,在任何情况下我的答案都不能被标记为正确答案。
答案 2 :(得分:0)
我和@ victor-wong有相同的错误消息
Could not instantiate bean class [class name]: Specified class is an interface
以下代码解决了以下问题
Spring Boot 2.3.2
和spring-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