Java 如何在JPA中映射自定义集合?
我在使用JPA(Hibernate提供程序)映射自定义集合时遇到问题。例如,当我使用带有属性的对象时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; } 谢谢你的关注 您可以,但您必须将其作为公共集合之一引用-列表或集合 因此: 为什么??例如,
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; }
}