如何在JPA中拥有2个相同类型的集合?

时间:2009-03-21 19:31:31

标签: java hibernate jpa collections persistence

我在JPA中有2个实体:Entry和Comment。 Entry包含两个Comment对象集合。

@Entity
public class Entry {
    ...

    @OneToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL)
    @IndexColumn(base = 1, name = "dnr")
    private List<Comment> descriptionComments = new ArrayList<Comment>();

    @OneToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL)
    @IndexColumn(base = 1, name = "pmnr")
    private List<Comment> postMortemComments = new ArrayList<Comment>();

    ...
}

要存储此类对象,JPA + Hibernate会创建“Entry”表,“Comment”表和SINGLE“Entry_Comment”:

create table Entry_Comment (Entry_id integer not null, postMortemComments_id integer not null, pmnr integer not null, descriptionComments_id integer not null, dnr integer not null, primary key (Entry_id, dnr), unique (descriptionComments_id), unique (postMortemComments_id))

对象的存储失败,因为descriptionComments_idpostMortemComments_id不能同时“不为空”。

如何使用JPA + Hibernate存储包含两个相同类型集合的对象?

4 个答案:

答案 0 :(得分:13)

这是许多Hibernate错误之一(准确地说是HHH-3410)。

我设法通过向@JoinTable关系添加@OneToMany注释来修复它,每个关系都有自己的表名。

在你的情况下,它看起来像这样:

@OneToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL)
@JoinTable(name="entity_descriptioncomments")
@IndexColumn(base = 1, name = "dnr")
private List<Comment> descriptionComments = new ArrayList<Comment>();

@OneToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL)
@JoinTable(name="entity_postmortemcomments")
@IndexColumn(base = 1, name = "pmnr")
private List<Comment> postMortemComments = new ArrayList<Comment>();

注意:您还必须添加@IndexColumn注释(因为多个EAGER包的其他Hibernate问题:HHH-1718 / EJB-346)。

答案 1 :(得分:4)

要使用 DataNucleus http://www.datanucleus.org)在JPA中存储2个类似的集合,您可以完全按照自己的意愿执行操作。您没有@JoinTable注释,因此对于每个集合,FK应放在Comment中。如果你确实在某处(或等效的XML)有@JoinTable,那么设置相应连接表的名称(每个集合一个)也可以工作(因此它们有自己的连接表)。在DataNucleus中也可以在2个集合之间建立共享连接表,但这不是标准JPA,而是供应商扩展。

如何映射到Hibernate我不知道,但是这是JPA所以应该保持一致,因为这是规范的要点; - )

答案 2 :(得分:2)

从数据模型/域模型的角度来看当前映射存在一个缺陷:您在 Entry 单个 @OneToMany 关系>和评论评论实体应该还有一个名为 type 的属性,它带有2个值:' description '或' postMortem '

要与您当前的 Entry 实体实现内联,您可能需要考虑将 Comment 实体分解为2个不同的实体(可能使用JPA继承功能)并使用< em> @JoinTable 注释条目

答案 3 :(得分:0)

如果您只关心订购,那么如何将两个索引列定义配置为具有相同的名称?