Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to have 2 collections of the same type in JPA?

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?

like image 659
Vilmantas Baranauskas Avatar asked Mar 21 '09 19:03

Vilmantas Baranauskas


People also ask

Can a JPA entity have multiple Onetomany associations?

You can have as many of them as you want.

What type of collections can be used in JPA?

JPA allows three kinds of objects to store in mapping collections - Basic Types, Entities and Embeddables.

How does JPA define many to one relationships?

Many-To-One relation between entities: Where one entity (column or set of columns) is/are referenced with another entity (column or set of columns) which contain unique values. In relational databases these relations are applicable by using foreign key/primary key between tables.


2 Answers

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).

like image 166
Idolon Avatar answered Oct 19 '22 13:10

Idolon


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

like image 38
DataNucleus Avatar answered Oct 19 '22 14:10

DataNucleus