Reputation: 2917
I'm using JPA annotations only and hibernate 4.0.1 as the JPA implementation.
I have anAssessment
class that has two sets of 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>();
}
(I'm skipping getters, setters, cascade annotations and other irrelevant lines of code)
Comment:
@Entity
@Table(name = "COMMENT")
public class Comment{
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
@Column(columnDefinition = "text")
private String text;
}
Now, because a Comment
doesn't have a reference back to Assessment
(this is on purpose), I cannot uset the mappedBy property and Hibernate needs to create a mapping table between Comment
and Assessment
. By default, it is named ASSESSMENT_COMMENT.
If I had only one set of Comment
in Assessment
, that would work perfectly fine. The ASSESSMENT_COMMENT would have only two columns:
[ASSESSMENT_ID, COMMENT_ID]
which will perfectly represent the one-to-many relationship.
Now here is the problem:
Because I don't have one set of Comment
but two, Hibernate tries to map the two sets using only one ASSESSMENT_COMMENT table. This table has 3 columns:
[ASSESSMENT_ID, COMMENT_ID, AUDITCOMMENT_ID]
On top of that, the 3 columns are set as non nullable.
That certainly cannot work. For instance, if I have only one item in auditComents and none in comments, hibernate tries to insert one row with a null in COMMENT_ID which creates a SQL exception.
Questions:
To me it looks like a bug. There should be two mapping tables, not one.
So, 1) is it a known bug in Hibernate? 2) is there a way around that? Can I force Hibernate to create two mapping tables, one for each of the set. Bear in mind that I cannot change the Comment
class to have a reference to Assessment
(business logic requirement)
Upvotes: 5
Views: 13547
Reputation: 692151
First of all, you could use two columns in the comment table to point back to their assessment:
@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>();
If you want two join tables, the just say so:
@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>();
That is of course explained in the documentation.
Upvotes: 8