2013-02-15 83 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