Anonymous Beaver
Anonymous Beaver

Reputation: 419

How do I map a One To Many Relationship with Composite Primary Key in JPA (Hibernate)?

My tables look like this:

School
-------
school_id (pk)
...

Student
school_id (pk) (fk)
student_id (pk)
...

So using JPA (Hibernate), I tried something like this.

@Entity
@Table("SCHOOL")
public School {
    @Column(name = "SCHOOL_ID")
    private String schoolId;
    
    @OneToMany
    private List<Student> students;
}

@Entity
@Table("STUDENT")
public Student {
    @EmbeddedId
    private StudentPK studentPK;

    @ManyToOne
    @JoinColumn(name = "SCHOOL_ID")
    private School school; 
}

@Embeddable
public StudentPK implements Serializable {
    @Column(name = "SCHOOL_ID")
    private String schoolId;

    @Column(name = "STUDENT_ID"
    private String studentId;
}

When I do this, I frequently get an error that says that the foreign key constraint is being violated on runtime. I suspect that JPA is trying to generate a new foreign key called "SCHOOL_ID" instead of using the existing column from my composite key, but I'm not sure how to force it to use the existing column.

Upvotes: 6

Views: 10813

Answers (1)

Brian Vosburgh
Brian Vosburgh

Reputation: 3276

These relationships should be mapped a bit differently:

@Entity
@Table("SCHOOL")
public School {
    @Column(name = "SCHOOL_ID")
    private String schoolId;
    
    @OneToMany(mappedBy="school")
    private List<Student> students;
}

@Entity
@Table("STUDENT")
public Student {
    @EmbeddedId
    private StudentPK studentPK;

    @ManyToOne
    @MapsId("schoolId")
    private School school; 
}

@Embeddable
public StudentPK implements Serializable {
    @Column(name = "SCHOOL_ID")
    private String schoolId;

    @Column(name = "STUDENT_ID"
    private String studentId;
}

Note the @OneToMany.mappedBy attribute on School.students and @MapsId annotation on Student.school.

Derived identities are discussed (with examples) in the JPA 2.2 spec in section 2.4.1.

Upvotes: 8

Related Questions