Many to Many hibernate inverse side ignored

前端 未结 2 1804
离开以前
离开以前 2020-12-10 06:05

Hi am reading the hibernate documentation.

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

A many-to-many associ

相关标签:
2条回答
  • 2020-12-10 06:20

    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.

    0 讨论(0)
  • 2020-12-10 06:21

    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;
    }
    
    0 讨论(0)
提交回复
热议问题