Hi am reading the hibernate documentation.
http://docs.jboss.org/hibernate/annotations/3.5/reference/en/html/entity.html
A many-to-many association is defined logically using the @ManyToMany annotation. You also have to describe the association table and the join conditions using the @JoinTable annotation. If the association is bidirectional, one side has to be the owner and one side has to be the inverse end (ie. it will be ignored when updating the relationship values in the association table):
I understand everything but the last
(ie. it will be ignored when updating the relationship values in the association table).
What does this mean? Example?
Suppose you have the following entities:
@Entity
public class Student {
@ManyToMany
private Set<Course> courses;
...
}
@Entity
public class Course {
@ManyToMany(mappedBy = "courses")
private Set<Student> students;
...
}
The owner side is Student (because it doesn't have the mappedBy
attribute). The inverse side is 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 in the join table because you updated the owner side of the association (student.courses
).
Whereas 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 inverse side of the association (course.students
), but neglected to updated the owner side. Hibernate only considers the owner side.
To make it work both ways you need to have two separate relationships between your entities. This can be represented by one join table in database but by default it will be represented by two so you have to explicitly say you want one join table.
I will demonstrate it using previously mentioned model of Student and Course.
@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 Student<->Course relationship being owner of one relation. So this solves the problem of saving changes to database only on the owner side since each side is owner of one relation.
But we have to keep in mind one fact that after saving data, relationship collections will NOT be reloaded from database so programmer need to handle relationship collections by himself. By saying this I want to say that the easiest way is to modify setters for relationship collections to rebuild cycle between entities like this:
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;
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With