首页 > 解决方案 > 如何将 2 个字段映射到同一个多对多关联?

问题描述

有一个 Spring JPA 应用程序:

对于一个用例,我想将所有学生数据读入一组学生,如下面的第一个集合(CourseRepository.findAll()) - 这仅用于读取与课程相关联的学生。

对于第二个用例,我想仅使用学生 UUID 来读取和更新学生集(因为这明显更快,避免了许多连接/级联) - 如下面的第二个集 - 这仅用于添加或删除学生一门课程。

@Entity
@Table(...)
public class Course {
    @Id
    private UUID id;

   @ManyToMany(fetch = FetchType.LAZY, cascade = {CascadeType.DETACH, CascadeType.MERGE, CascadeType.REFRESH, CascadeType.PERSIST})
   @JoinTable(
       schema = "...",
       name = "...",
       joinColumns = {@JoinColumn(name = "course_id", referencedColumnName = "id")},
       inverseJoinColumns = {@JoinColumn(name = "student_id", referencedColumnName = "id")}
   )
   private Set<Student> students = new java.util.HashSet<>();

   @ManyToMany
   @JoinTable(
       schema = "...",
       name = "...",
       joinColumns = {@JoinColumn(name = "course_id", referencedColumnName = "id")},
       inverseJoinColumns = {@JoinColumn(name = "student_id", referencedColumnName = "id")}
    )
   private Set<UUID> students = new java.util.HashSet<>();
   ...
}

@Entity
@Table(name="student")
public class Student {
    @Id
    private UUID id;

    private String name;
...
}

@Repository
public interface CourseRepository extends JpaRepository<Course, UUID> {}

标签: hibernatejpaspring-data-jpahibernate-mapping

解决方案


您应该将多对多关联建模为两个一对多关联,因为无论如何这都是您最终需要的。这样,可以通过简单地持久化这个新CourseStudentAssignment实体来完成分配。

@Entity
public class CourseStudentAssignment {
    @EmbeddedId
    CourseStudentAssignmentId id;
    @ManyToOne(fetch = LAZY)
    @MapsId("courseId")
    Course course;
    @ManyToOne(fetch = LAZY)
    @MapsId("studentId")
    Student student;

}
@Embeddable
public class CourseStudentAssignmentId {
    UUID courseId;
    UUID studentId;
}
@Entity
@Table(...)
public class Course {
    @Id
    private UUID id;

   @OneToMany(mappedBy = "course", fetch = FetchType.LAZY, cascade = {CascadeType.DETACH, CascadeType.MERGE, CascadeType.REFRESH, CascadeType.PERSIST})
   private Set<CourseStudentAssignment> studentAssignments = new java.util.HashSet<>();

}
@Entity
@Table(...)
public class Student {
    @Id
    private UUID id;

   @OneToMany(mappedBy = "student", fetch = FetchType.LAZY, cascade = {CascadeType.DETACH, CascadeType.MERGE, CascadeType.REFRESH, CascadeType.PERSIST})
   private Set<CourseStudentAssignment> courseAssignments = new java.util.HashSet<>();

}

推荐阅读