15

I've got 2 entities in JPA: Entry and Comment. Entry contains two collections of Comment objects.

@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>();

    ...
}

To store such objects, JPA+Hibernate creates "Entry" table, "Comment" table and 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))

Storing of objects fail as descriptionComments_id and postMortemComments_id cannot be "not null" at the same time.

How do I store object containing two collections of the same type using JPA+Hibernate?

4

4 回答 4

13

This is one of the many Hibernate bugs (HHH-3410 to be precise).

I've managed to fix it by adding @JoinTable annotations to @OneToMany relationships, each having its own table name.

In your case it would look like this:

@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>();

Note: you must add @IndexColumn annotation as well (because of the other Hibernate issue with multiple EAGER bags: HHH-1718/EJB-346).

于 2009-07-03T09:51:24.617 回答
4

To store 2 collections like that in JPA with DataNucleus (http://www.datanucleus.org) you would do exactly as you've done. You have no @JoinTable annotation hence a FK should be placed in Comment for each of the collections. If you actually do have @JoinTable somewhere (or XML equivalent) then setting the names of the respective join tables (one for each collection) would work too (so they have their own join table). Having a shared join table between 2 collections is possible in DataNucleus too, but that's not standard JPA, instead a vendor extension.

How that maps to Hibernate I've no idea, but then this is JPA so should be consistent since thats the point of having a spec ;-)

于 2009-03-22T17:35:01.797 回答
2

There is a flaw with current mapping from data model/domain model point of view: you actaully have a single @OneToMany relationship between Entry and Comment. And Comment entity should have one more attribute called type that takes 2 values: 'description' or 'postMortem'.

To be inline with your current implementation of Entry entity you may want to consider breaking down Comment entity into 2 different entities (possibly using JPA inheritance features) and using @JoinTable annotation in Entry.

于 2009-03-22T17:46:22.893 回答
0

If all you care about is ordering, how about configuring the two index column definitions to have the same name?

于 2009-03-23T02:45:01.943 回答