@ManyToMany (bidirectional)

studentstudent_coursecourse

id (PK) name

student_id (PK, FK) course_id (PK, FK)

id (PK) name

student_course 叫做一个 Join Table(中间表)。

使用 Spring Data JPA 实现:

@Entity
@Getter
@Setter
class Student {
    @Id
    Long id;

    @ManyToMany(cascade = {
        CascadeType.PERSIST,
        CascadeType.MERGE
    })
    @JoinTable(
        name = "student_course",
        joinColumns = {@JoinColumn(name = "student_id")},
        inverseJoinColumns = {@JoinColumn(name = "course_id")}
    )
    Set<Course> courses;
}
@Entity
@Getter
@Setter
class Course {
    @Id
    Long id;

    @ManyToMany(mappedBy = "courses")
    Set<Student> students;
}

在这里,我们决定 Student 是 owning side。这个决定并没有特别的原因,在一个 Many-to-Many 关系中,两个表的关系应该是对等的。

中间表由 @JoinTable 指定生成。

@JoinColumns points to the owning side table (student) and @InverseJoinColumns points to the inverse table of the owning side (course).

其实也可以省略 @JoinTable 注解,Spring Data JPA 会帮助我们自动生成,但是 JPA 生成的和我们的预期不总是一致,所以最好不要省略 @JoinTable@JoinColumn

As you can see in the example, I'm using Set rather than List in my association. This is because Hibernate deletes all the rows in student_course link to that entity, and re-insert the ones we did not want to delete. This is of course not efficient and unnecessary.

注意:为了保证性能,在 Many-to-Many 关系中应该使用 java.util.Set 作为引用的容器,而不是 java.util.List

为了保证 java.util.List 中元素的顺序,Hibernate 会先把元素全部删除,任何再把你不想删除的一个个顺序插入进去,效率很低,所以最好使用 java.util.Set

最后更新于