如何在 JPA 中映射自定义集合?
Posted
技术标签:
【中文标题】如何在 JPA 中映射自定义集合?【英文标题】:How to map custom collection in JPA? 【发布时间】:2011-03-11 14:29:01 【问题描述】:我在使用 JPA(Hiberante 提供程序)映射自定义集合时遇到问题。例如,当我使用具有属性的对象时
List<Match> matches;
与
<one-to-many name="matches">
<cascade>
<cascade-all />
</cascade>
</one-to-many>
在我的ORM文件中,没关系;但是如果我将 "List matches;" 替换为
private Matches matches;
,其中 "Matches" 定义如下:
public class Matches extends ArrayList<Match>
private static final long serialVersionUID = 1L;
它会产生以下错误:
Caused by: org.hibernate.AnnotationException: Illegal attempt to map a non collection as a @OneToMany, @ManyToMany or @CollectionOfElements: by.sokol.labs.jpa.MatchBox.matches
感谢您的关注!
【问题讨论】:
【参考方案1】:您可以,但您必须将其称为常见集合之一 - List
或 Set
。
所以:
private List matches = new Matches();
为什么?例如,因为 Hibernate 会代理您的集合以启用延迟加载。因此它创建了PersistentList
、PersistentSet
和PersistentBag
,它们是List
,但不是Matches
。因此,如果您想向该集合添加其他方法 - 好吧,您不能。
Check this article了解更多详情。
不过,您有一个解决方案。不要使用继承,使用组合。例如,您可以向您的实体添加一个名为 getMatchesCollection()
的方法(除了传统的 getter),如下所示:
public Matches getMatchesCollection()
return new Matches(matches);
你的Matches
类看起来像(使用google-collections'ForwardingList
):
public class Matches extends ForwardingList
private List<Match> matches;
public Matches(List<Match> matches) this.matches = matches;
public List<Match> delegate() return matches;
// define your additional methods
如果你不能使用google集合,只需自己定义ForwardingList
- 它调用底层List
的所有方法
如果您不需要任何额外的方法来对结构进行操作,则不要定义自定义集合。
【讨论】:
【参考方案2】:Hibernate 需要将持久的集合值字段声明为接口类型(因为它们将被 Hibernate 的实现替换以实现延迟加载)。来自参考文档:
6.1. Persistent collections
Hibernate 要求将持久的集合值字段声明为接口类型。例如:
public class Product private String serialNumber; private Set parts = new HashSet(); public Set getParts() return parts; void setParts(Set parts) this.parts = parts; public String getSerialNumber() return serialNumber; void setSerialNumber(String sn) serialNumber = sn;
实际的界面可能是
java.util.Set
,java.util.Collection
,java.util.List
,java.util.Map
,java.util.SortedSet
,java.util.SortedMap
或任何你喜欢的东西 喜欢(“你喜欢的任何东西”是指你 将不得不编写一个实现 的org.hibernate.usertype.UserCollectionType
.)注意实例变量是如何 用一个实例初始化
HashSet
。这是最好的方法 初始化集合值 新实例化的属性 (非持久)实例。当你 使实例持久化,通过 例如,调用persist()
, Hibernate 实际上将取代HashSet
有一个实例 Hibernate 自己实现的Set
。
所以你的第二种方法是不可能的,至少不是你声明的方式。但老实说,我真的不明白这一点。
【讨论】:
以上是关于如何在 JPA 中映射自定义集合?的主要内容,如果未能解决你的问题,请参考以下文章