如何在 JPA (Hibernate) 中映射具有复合主键的一对多关系?

Ano*_*ver 6 java hibernate jpa spring-data-jpa

我的桌子看起来像这样:

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

Student
school_id (pk) (fk)
student_id (pk)
...
Run Code Online (Sandbox Code Playgroud)

所以使用JPA(Hibernate),我尝试了这样的事情。

@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;
}

Run Code Online (Sandbox Code Playgroud)

当我这样做时,我经常收到一个错误,指出运行时违反了外键约束。我怀疑 JPA 正在尝试生成一个名为“SCHOOL_ID”的新外键,而不是使用复合键中的现有列,但我不确定如何强制它使用现有列。

Bri*_*rgh 6

这些关系的映射应该略有不同:

@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;
}

Run Code Online (Sandbox Code Playgroud)

请注意@OneToMany.mappedBy上的属性School.students@MapsId注释Student.school

JPA 2.2 规范的第 2.4.1 节讨论了派生身份(并附有示例)。