Many for many sleep mode, the flip side is ignored

Hi, I am reading sleep mode documentation.

http://docs.jboss.org/hibernate/annotations/3.5/reference/en/html/entity.html

Many-to-many connectivity is determined logically using the @ManyToMany annotation function. You should also describe the association table using the @JoinTable annotation. If the association is bidirectional, one side should be the owner, and one side should be the opposite end (i.e. it will be ignored when updating the value relationship in the association table):

I understand everything except the last

(i.e., it will be ignored when updating relationship values ​​in the association table).

What does it mean? Example?

+7
source share
2 answers

Suppose you have the following objects:

@Entity public class Student { @ManyToMany private Set<Course> courses; ... } @Entity public class Course { @ManyToMany(mappedBy = "courses") private Set<Student> students; ... } 

The own side is the Student (since he does not have the mappedBy attribute). The mappedBy side is the course ((because it has the mappedBy attribute).

If you do the following:

 Course course = session.get(Course.class, 3L); Student student = session.get(Student.class, 4L); student.getCourses().add(course); 

Hibernate will add an entry for student 4 and course 3 to the connection table because you have updated the association owner side ( student.courses ).

If you do the following:

 Course course = session.get(Course.class, 3L); Student student = session.get(Student.class, 4L); course.getStudents().add(student); 

nothing will happen because uou updated the back of the association ( course.students ) but neglected the updated side of the owner. Hibernate only considers the owner side.

+22
source

In order for it to work in both directions, you need to have two separate connections between your entities. This may be represented by a single join table in the database, but by default it will be represented by two, so you must explicitly say that you want one join table.

I will demonstrate this using the previously mentioned Student and Course model.

 @Entity public class Student { @ManyToMany @JoinTable(name = "student_course", joinColumns = {@JoinColumn(name = "courses_id")}, inverseJoinColumns = {@JoinColumn(name = "students_id")}) private Set<Course> courses; ... } @Entity public class Course { @ManyToMany @JoinTable(name = "student_course", joinColumns = {@JoinColumn(name = "students_id")}, inverseJoinColumns = {@JoinColumn(name = "courses_id")}) private Set<Student> students; ... } 

In the above example, we have 2 relationships with each side of the Student <Course relationship that owns one relationship. Thus, this solves the problem of saving changes to the database only on the side of the owner, since each side is the owner of one relationship.

But we must bear in mind one fact that after saving the data, the relationship collections will NOT be reloaded from the database, so the programmer needs to process the relationship collections on his own. Having said that, I want to say that the easiest way is to modify the setters for relationship collections in order to rebuild the cycle between such objects:

 public void setCourses(Set<Course> courses) { for(Course c : courses) { if (!c.getStudents().contains(this)) { c.getStudents().add(this); } } this.courses = courses; } public void setStudents(Set<Student> students) { for(Student s : students) { if (!s.getCourses().contains(this)){ s.getCourses().add(this); } } this.students = students; } 
+2
source

All Articles