如何使用Spring Data(MongoDB)映射通用集合?

3

我在映射内部集合时遇到了一些问题。不同的项目可以有不同的内容类型。这是我的Item类:

@Document(collection = "items")
public class Item{
@Id
private ObjectId id;   
private List<? super Content> content;
...
}

Content 是此项目中不同内容的基类。

public class YoutubeVideo implements Content{
     private String url;
}

public class Image implements Content{
     private String location;
}
...

保存内容集合中一个包含一张图片和两个Youtube视频类的物品后,我得到了以下的JSON数据

{ "_id" : { "$oid" : "4e423dcf7f3a0d12265da46c"} 
"content" : [ 
{ "location" : "hdd path"} , { "url" : "url path"} , { "url" : "url path"}
]}

我看到的JSON并不是我期望的那个。很容易理解为什么无法加载和反序列化这个文档。

java.lang.RuntimeException: Can not map ? super trngl.mongo.domain.content.Content

你如何映射这种类型的对象?我不想手动序列化和反序列化对象。这可行吗?
发现了有趣的转换器类:mapping-explicit-converters
3个回答

5

提醒一下(我们在尝试弄清楚为什么返回的对象会是成员 LinkedHashMaps 后花了整整一个早上来搜索此问题),当您尝试以以下形式存储 Collection<Content> 时,此问题也会发生(在1.0.2.RELEASE版本中):

@Document(collection = "items")
public class Item{
@Id
private ObjectId id;   
private Collection<Content> content;
...
}

解决方法如上所述,是将其切换为一个List<Content>

5

只需要使用List<Content>就足够了,因为无论如何都无法从混合内容列表中访问具体类型。(顺便说一下,使用super肯定是错误的,因为你没有存储Content的超类型,而是子类型。另一方面,extends不会增加任何额外的价值)。

如果您使用最新版本的MongoTemplate快照,则List<Content>应该可以正常工作,因为我们自上一个里程碑版本以来修复了相当多的bug。如果您正在使用我们的存储库抽象,请确保Content是一个包含id属性的抽象类。有一个未解决的问题,您可以关注我们是否支持接口作为存储库管理的类型。


嗨,Oliver。谢谢你。你是对的。使用1.0.0.M3,一切都像我预期的那样工作,我看到了额外的'_class'属性。但现在我所有的类都有这个属性。我只需要在存储在此集合中的对象中拥有此属性。你能帮我吗?是否可以将此属性添加到特定的类中? - Tim
这个改变在 M4 版本中是否有所不同呢?它似乎不再按照这里描述的方式工作了。 - Justin Hamade
这个集合需要任何注释吗? - Pedro Dusso

0

代码 List<? super Content> content; 创建了一个元素为类型,扩展自Content类的列表。我看到Content是一个接口,所以你不能为它指定通用绑定。

我建议你创建一个抽象类Content,并通过你的类YoutubeVideoImage来扩展这个类。之后,代码List<? super Content> content;将正常工作。

Sergey。


嗨,Sergei。不,你错了。保存后的JSON是相同的。问题不在于Java类中,而是在序列化/反序列化器中。保存的JSON没有任何真实的类ID,这就是为什么无法反序列化JSON的原因。 - Tim

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接