JPA/Hibernate的一对多关系表映射

5

我只使用JPA注释和Hibernate 4.0.1作为JPA实现。

我有一个Assessment类,其中有两组Comment

@Entity
@Table(name = "ASSESSMENT")
public class Assessment{

    @OneToMany(fetch = FetchType.EAGER)
    private Set<Comment> auditComments = new HashSet<Comment>();

    @OneToMany(fetch = FetchType.EAGER)
    private Set<Comment> comments = new HashSet<Comment>();
}
< p > < em > (我跳过了获取器,设置器,级联注释和其他不相关的代码行)

评论:

@Entity
@Table(name = "COMMENT")
public class Comment{

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;

    @Column(columnDefinition = "text")
    private String text;
}

现在,由于Comment没有指向Assessment的引用(这是故意的),我不能使用mappedBy属性,Hibernate需要在CommentAssessment之间创建一个映射表。默认情况下,它的名字为ASSESSMENT_COMMENT。

如果在Assessment中只有一组Comment,那么就可以完美地工作。 ASSESSMENT_COMMENT将只有两列:

[ASSESSMENT_ID, COMMENT_ID]

这将完美地表示一对多的关系。

现在问题来了:

因为我有两个 Comment 集合,Hibernate 试图仅使用一个 ASSESSMENT_COMMENT 表来映射这两个集合。该表有3列:

[ASSESSMENT_ID, COMMENT_ID, AUDITCOMMENT_ID]

此外,这3列被设置为非空。但是这样显然行不通。例如,如果auditComents中只有一个项目,而comments中没有,则Hibernate尝试插入一个带有COMMENT_ID为空的行,从而创建SQL异常。
问题:
在我看来,这似乎是一个错误。应该有两个映射表,而不是一个。
那么,1)Hibernate中是否已知此错误?2)有没有办法解决它?我能否强制Hibernate创建两个映射表,分别用于每个集合?请注意,我无法更改Comment类以引用Assessment(业务逻辑要求)。
1个回答

8

首先,您可以在评论表中使用两列来指向他们的评估:

@OneToMany(fetch = FetchType.EAGER)
@JoinColumn(name = "audit_commented_assessment_id")
private Set<Comment> auditComments = new HashSet<Comment>();

@OneToMany(fetch = FetchType.EAGER)
@JoinColumn(name = "commented_assessment_id")
private Set<Comment> comments = new HashSet<Comment>();

如果你想要连接两个表,只需要明确说明即可。
@OneToMany(fetch = FetchType.EAGER)
@JoinTable(name = "assessment_audit_comment",
           joinColumns = @JoinColumn(name = "assessment_id"),
           inverseJoinColumns = @JoinColumn(name = "comment_id"))
private Set<Comment> auditComments = new HashSet<Comment>();

@OneToMany(fetch = FetchType.EAGER)
@JoinTable(name = "assessment_comment",
           joinColumns = @JoinColumn(name = "assessment_id"),
           inverseJoinColumns = @JoinColumn(name = "comment_id"))
private Set<Comment> comments = new HashSet<Comment>();

这当然在文档中有解释。


谢谢,问题已解决。我以前从未有过两个相同类型的集合,所以我从未使用过@JoinTable注释。 - phoenix7360
如果您想要建立双向关系,Comment类应该如何编写呢?例如,在Comment POJO中,我想引用一个Assessment对象,但不能使用两个@jointable(一个针对每个父表)。您会如何处理? - nize
2
如果关联是双向的,你需要将Comment作为关联的拥有方。在Comment中,你会有一个字段commentedAssessment和一个字段auditedAssessment。它们将使用@ManyToOne进行映射,使用上面的连接表,但是连接列和反向连接列会交换。在Assessment中,你只需要有@OneToMany(mappedBy = "auditedAssessment") private Set<Comment> auditComments;@OneToMany(mappedBy = "commentedAssessment") Set<Comment> comments; - JB Nizet
好的,但是假设情况是评论必须是审核评论或者评论,而不是两者都有。这就是为什么我希望评论只有一个“评估父级”的引用,而不是“评论评估”和“审核评估”两个引用。是否可能实现这一点,或者我需要有两个引用,其中一个始终为空?也许我需要扩展评论类,创建AuditComment和NormalComment两个类? - nize
我曾尝试过这条路,但由于对超类的 mappedBy 引用并不像我预期的那样有效,所以我发现它是一团乱麻。我决定尝试另一种方案:在 Assessment 类中,我有一个 List<Comment> comments。在 Comment 类中,我使用一个布尔值 isAuditComment。然后我可以在 Assessment 类中提供像 List<Comment> getAuditingComments() 和 List<Comment> getOtherComments() 这样的方法。虽然不太优雅,但从 JPA 的角度来看更简单。 - nize

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接