Java 如何在JPA中映射自定义集合?

Java 如何在JPA中映射自定义集合?,java,hibernate,collections,jpa,persistence,Java,Hibernate,Collections,Jpa,Persistence,我在使用JPA(Hibernate提供程序)映射自定义集合时遇到问题。例如,当我使用带有属性的对象时 List<Match> matches; ,其中“匹配”的定义如下: public class Matches extends ArrayList<Match> { private static final long serialVersionUID = 1L; } 谢谢你的关注 您可以,但您必须将其作为公共集合之一引用-列表或集合 因此: 为什么??例如,

我在使用JPA(Hibernate提供程序)映射自定义集合时遇到问题。例如,当我使用带有属性的对象时

List<Match> matches;
,其中“匹配”的定义如下:

public class Matches extends ArrayList<Match> {

    private static final long serialVersionUID = 1L;
}

谢谢你的关注

您可以,但您必须将其作为公共集合之一引用-
列表
集合

因此:

为什么??例如,因为Hibernate对集合进行代理以启用延迟加载。因此,它创建了
PersistentList
PersistentSet
PersistentBag
,它们是
List
,但不是
匹配项。因此,如果您想向该集合添加其他方法,那么您不能

更多细节

然而,你有一个解决办法。不要使用继承,使用组合。例如,您可以向实体添加一个名为
getMatchesCollection()
(除了传统的getter之外)的方法,该方法如下所示:

 public Matches getMatchesCollection() {
    return new Matches(matches);
 }
您的
匹配项
类将如下所示(使用“
ForwardingList
):

公共类匹配扩展了ForwardingList{
私人列表匹配;
公共匹配(列表匹配){this.Matches=Matches;}
公共列表委托(){返回匹配项;}
//定义其他方法
}
如果您不能使用google collections,只需自己定义
ForwardingList
——它调用底层
List


如果不需要任何其他方法对结构进行操作,则不要定义自定义集合。

Hibernate要求将持久集合值字段声明为接口类型(因为它们将被Hibernate的实现替换,以实现延迟加载)。参考文件:

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

因此,您的第二种方法是不可能的,至少不是您声明的方式。但说实话,我真的不明白这一点

Caused by: org.hibernate.AnnotationException: Illegal attempt to map a non collection as a @OneToMany, @ManyToMany or @CollectionOfElements: by.sokol.labs.jpa.MatchBox.matches
private List matches = new Matches();
 public Matches getMatchesCollection() {
    return new Matches(matches);
 }
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
}
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; }
}