45

I have following tables how can i map them to JPA entities:

TABLE Event {
    EventID
    SourceID
    ....Other event fields
    PK (EventID, SourceID)
}

TABLE MEETING {
    MeetingID
    EventID
    SourceID
    ...Other meeting fields
    PK(MeetingID,EventID, SourceID)
    FK(EventID, SourceID) //FK with Event table
}

The Event table has one-to-many relationship with Meeting table. How can i map this bi-directional relationship in JPA?

Jin Kwon
  • 20,295
  • 14
  • 115
  • 184
suraj bahl
  • 2,864
  • 6
  • 31
  • 42
  • We got what you want to say but you may wanna edit your question. A table cannot have multiple Primary Keys. http://stackoverflow.com/questions/20742922/can-a-table-have-multiple-primary-keys – Raman Sahasi Jul 13 '15 at 17:28

2 Answers2

51
@Embeddable
public class EventID {
    public int eventID;
    public int sourceID;
}

@Entity
public class Event {
    @EmbeddedId
    public EventID id;

    @OneToMany(mappedBy="event")
    public Collection<Meeting> meetings;
}

@Embeddable
public class MeetingID {
    public EventID eventID; // corresponds to ID type of Event
    public int meetingID;
}

@Entity
public class Meeting {
    @EmbeddedId
    public MeetingID id;

    @MapsId("eventID")
    @JoinColumns({
        @JoinColumn(name="EventID", referencedColumnName="EventID"),
        @JoinColumn(name="SourceID", referencedColumnName="SourceID")
    })
    @ManyToOne
    public Event event;
}

Discussed in JPA 2.1 spec, section 2.4.1.

Brian Vosburgh
  • 3,146
  • 1
  • 18
  • 18
  • In this case, do I need to set meetingID manually? Or Can i generate randomically? – Cristiano Bombazar Sep 20 '19 at 01:14
  • 2
    @CristianoBombazar - you can set meetingID either way; but it is probably more common to set the value manually, as it typically has some semantic meaning and/or is scoped by the associated Event. Thus the composite primary key. – Brian Vosburgh Sep 20 '19 at 13:16
  • I have a similar situation where my pk and FK share a field, but not all FK fields are in pk. I managed to make it work with your example, however, I always had to set meetingID manually. Is this behavior correct? – Cristiano Bombazar Sep 20 '19 at 14:27
  • 1
    @CristianoBombazar - yes, you will need to set meetingID manually. – Brian Vosburgh Sep 21 '19 at 23:35
  • 2
    Do I have set both meeting Id and event? Since event is mapped by eventId in meetingId would it not be enough to set meetingId? – Andrews Dec 25 '20 at 12:55
  • 1
    Section 2.4.1 also has a number of examples of how to do this for every combination of IdClass and EmbeddedId on parent and child. One quick gotcha is that when using the IdClasses the field name needs to be the same in the IdClass and in the child entity itself. – Alex May 17 '23 at 14:50
12
@Entity
public class Event {

    @EmbeddedId
    private EventId id;

    @OneToMany(mappedBy = "event")
    private List<Meeting> meetings = new ArrayList<>();
}

@Embeddable
public class EventId implements Serializable {

    @Column(name = "EventID")
    private Long eventId;

    @Column(name = "SourceID")
    private Long sourceId;

    //implements equals and hashCode
}

@Entity
public class Meeting {

    @EmbeddedId
    private MeetingId id; 

    @MapsId("eventId")
    @JoinColumns({
        @JoinColumn(name="EventID", referencedColumnName="EventID"),
        @JoinColumn(name="SourceID", referencedColumnName="SourceID")
    })
    @ManyToOne
    private Event event;
}

@Embeddable
public class MeetingId implements Serializable {

    @Column(name = "MeetingID")
    private Long meetingId;

    private EventId eventId;

    //implements equals and hashCode
}

You may want to take a look at a similar question for more details.

Community
  • 1
  • 1
Dragan Bozanovic
  • 23,102
  • 5
  • 43
  • 110