Home > Net >  in Spring jpa using the @ManyToMany relationship, why create a new class with @Embeddable?
in Spring jpa using the @ManyToMany relationship, why create a new class with @Embeddable?

Time:10-14

According to the Spring JPA documentation, in the Many-To-Many relationship (student - course) we must create a new table (student_course)

class student ---> class student_course <--- class course

According to the documentation, if we want to add a new property to the table (student_course) we must create a new class that will contain the compound keys of the student class and the course class

@Embeddable
class CourseStudentKey implements Serializable {


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


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

_ Then to the Student_Course class we assign the id of type CourseStudentKey that contains the compound keys:

@Entity
class StudentCourse {

@EmbeddedId
CourseRatingKey id;

@ManyToOne
@MapsId("studentId")
@JoinColumn(name = "student_id")
Student student;

@ManyToOne
@MapsId("courseId")
@JoinColumn(name = "course_id")
Course course;
}

My question is: What is the difference in creating only the StudentCourse class and doing the @ManyToOne mapping to the Student class and the Course class??... in this way we can also add attributes to the StudentCourse class

_Clase Student

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

_Clase StudentCourse

@Entity 
class StudentCourse {

@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
private idStudentCourse;

@ManyToOne
@JoinColumn(name = "student_id")
Student student;

@ManyToOne
@JoinColumn(name = "course_id")
Course course;
}

CodePudding user response:

The only difference in the examples posted by you, is, in case of Embeddable, the student_id course_id would be a composite key, so there would only be one row allowed per student_id course_id combination. Whereas, in the second example, you have used genarated primary key, ensuring multiple rows for each student_id course_id combination. This would be particularly useful if the student fails the course for the first time and attempts it again. You can then add parameters like attemped_on, is_completed, etc. to the student_course entity

CodePudding user response:

Your examples show differences in the key, and as Chetan's answer states, this affects the key used in the table. The choices here isn't necessarily in using a separate class/embbeded class, but in using a single generated Identifier vs using a composite primary key for the entity.

In the embedded example you've posted, you have a composite primary key based on foreign key mappings. There are many other ways to map this same setup though, but the common parts will be:

  1. composite PKs need an ID class. It doesn't have to be embedded in your class (see JPA derived IDs) but does need to exist. This is part of the JPA spec and allows em.find operations to deal with a single object.
  2. ID values are immutable. They cannot change without remove/persist operations as per the JPA specification. Many providers don't like you even attempting to modify them in an Entity instance. In your embeddable example, you cannot change the references, while in the generated id example, you can.

It also affects what JPA requires you to use in foreign keys. If you use a composite ID, any references to that entity (*ToOne) that require foreign keys to that table are required to use its defined IDs - all columns that make up that ID. Some providers don't enforce this, but it will affect entity caching; since entities are cached on their IDs, using something else as the target of FKs might mean database hits for entities already in the cache.

  • Related