如何在 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】:

您可以,但您必须将其称为常见集合之一 - ListSet

所以:

private List matches = new Matches();

为什么?例如,因为 Hibernate 会代理您的集合以启用延迟加载。因此它创建了PersistentListPersistentSetPersistentBag,它们是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 中映射自定义集合?的主要内容,如果未能解决你的问题,请参考以下文章

SpringData JPA--解决将Map等集合类型映射到数据库的问题

jpa 实体bean中如何定义非映射字段

如何在 JPA 中生成自定义 ID

spring data jpa自定义bean字段映射

枚举的 JPA 映射集合

JPA集合映射