2013-02-15 54 views
2

我刚开始开发一些Java应用程序与弹簧数据的MongoDB和遇到一些问题,我一直没能解决传来:SD MongoDB的多态性子文档

有几个文件豆这样的:

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

@Docuemnt 
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); 
} 

保存酒吧工作得很好,它会保存在蒙戈沿Foo和Bar的“_class”属性。然而,在富一些属性找到会抛出这样的例外:

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) 

其中,一些挖后,有一定道理,因为无处查询是被指定的子文档的具体类型和实体Bar的信息表明foo的类型是Foo(而不是FooImpl),而Foo的类型又不具有属性,因此它是一个接口。

我的问题是:有没有一种方法来指定它或解决这个问题,而无需将子文档类型声明为具体类型?

我一直使用Google搜索几天,看文档和API和源代码,但我找不到一个明确的方法来做到这一点。我非常感谢你的帮助。

非常感谢。

+0

经过一些更多的测试后,我注意到当我保存一个对象然后从mongodb中检索文档时,一切都很好。 但是,当它是第一次从MongoDB读取时,我得到一个BeanInstantiationException。显然,objectCallback没有合适的TypeMapper,它可以将接口解析为具体的类来为DBObject实例化。 – Russell 2013-03-18 23:52:39

回答

3

我有一个类似的问题,我有一个实现接口的类,当我使用findAll我得到的错误:

org.springframework.data.mapping.model.MappingInstantiationException: Could not instantiate bean class [test.MetaClasse]: Specified class is an interface.

调试SpringData代码后,我意识到,映射器使用@TypeAlias发现的类型它必须实例化,所以我只把@TypeAlias("FullClassName")放在我的test.MetaClasse的实现上,它工作正常!

我测试过你的情况,它会工作!

+0

有没有其他解决方案?从设计角度来看,这看起来非常糟糕。你将不得不为每个'Foo'的实现添加一个@TypeAlias注解。 – jtcotton63 2017-02-17 18:34:36

+0

此外,这种方法使得重构非常困难。如果我需要重新命名课程怎么办?数据库中的所有_alias引用现在都是无用的。如果我需要创建一个类抽象然后添加子实现呢?再一次,_alias引用现在是无用的。我将不得不写一个脚本来通过数据并全部改变它们。必须有更好的解决方案。 – jtcotton63 2017-02-17 19:12:39