在使用@ManyToMany关系的Springjpa中,为什么要使用@Embeddable创建一个新类



根据Spring JPA文档,在多对多关系(学生-课程(中,我们必须创建一个新表(学生_课程(

班上的学生--->班级学生课程<---课堂

根据文档,如果我们想向表中添加一个新属性(student_scourse(,我们必须创建一个新的类,该类将包含学生类和课程类的复合键

@Embeddable
class CourseStudentKey implements Serializable {

@Column(name="student_id")
Long studentId;

@Column(name = "course_id")
Long courseId;
}

_然后,我们将CourseStudentKey类型的id分配给Student_Course类,该id包含复合键:

@Entity
class StudentCourse {
@EmbeddedId
CourseRatingKey id;
@ManyToOne
@MapsId("studentId")
@JoinColumn(name = "student_id")
Student student;
@ManyToOne
@MapsId("courseId")
@JoinColumn(name = "course_id")
Course course;
}

我的问题是:只创建StudentCourse类和将@ManyToOne映射到Student类和Course类有什么区别??。。。通过这种方式,我们还可以为StudentCourse类添加属性

_冲突学生

@Entity
class Student {
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
private idStudent;
@JsonIgnore
@OneToMany(mappedBy = "student")
List<StudentCourse> studentCourses = new ArrayList<>();

_Clase Course

@Entity
class Course{
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
private idCourse;
@JsonIgnore
@OneToMany(mappedBy = "course")
List<StudentCourse> studentCourses = new ArrayList<>();
}

_冲突研究课程

@Entity 
class StudentCourse {
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
private idStudentCourse;
@ManyToOne
@JoinColumn(name = "student_id")
Student student;
@ManyToOne
@JoinColumn(name = "course_id")
Course course;
}

您发布的示例中唯一的区别是,在Embeddable的情况下,student_id course_id将是一个复合键,因此每个student_id course_id组合只允许有一行。然而,在第二个示例中,您使用了生成的主键,确保每个student_id course_id组合有多行。如果学生第一次不及格并再次尝试,这将特别有用。然后,您可以将attemped_on, is_completed等参数添加到student_scourse实体中

您的示例显示了键的差异,正如Chetan的回答所说,这会影响表中使用的键。这里的选择不一定是使用单独的类/嵌入类,而是使用单个生成的标识符,而不是使用实体的复合主键。

在您发布的嵌入式示例中,您有一个基于外键映射的复合主键。不过,还有许多其他方法可以映射相同的设置,但常见的部分是:

  1. 复合PK需要一个ID类。它不必嵌入到类中(请参阅JPA派生的ID(,但必须存在。这是JPA规范的一部分,允许em.find操作处理单个对象
  2. ID值是不可变的。如果不按照JPA规范进行删除/持久化操作,它们就无法更改。许多提供者甚至不喜欢您尝试在实体实例中修改它们。在可嵌入的示例中,不能更改引用,而在生成的id示例中,可以

它还影响JPA要求您在外键中使用的内容。如果您使用复合ID,则对该实体(*ToOne(的任何引用(需要该表的外键(都需要使用其定义的ID-组成该ID的所有列。有些提供程序不强制执行此操作,但会影响实体缓存;由于实体被缓存在它们的ID上,使用其他东西作为FK的目标可能意味着已经在缓存中的实体的数据库命中率。

最新更新