简体   繁体   中英

Java - Hibernate @ManyToMany mapping adds records in the database only in one direction

I am new to Hibernate and I encountered a problem. I have two entities (Student and Course). Students can have many courses, and courses can have many students. When I am making a new course and add it to the database and in the same session I add this course to the student's courses (student.getCourses().add(course)) everything is working fine and records are added both in the Courses table and the Students_Courses table. When I do the same in the other direction it's not working correctly. First I add a new student in the database. I take an existing course and execute (course.getStudents().add(student)) but no record is saved in the Students_Courses table. Both the many to many mappings are PERSIST cascade, so it has to work.

Do you know what the problem might be? I am using MSSQL database.

First direction (not working - only the new student is saved in the database)

Session session = HibernateUtils.getSessionFactory().openSession();
    session.beginTransaction();
    {
        Faculty faculty = (Faculty) session.get(Faculty.class, 1);

        Student newStudent = new Student();
        newStudent.setFaculty(faculty);
        newStudent.setGrade(3.0);
        newStudent.setName("Some student name");

        session.save(newStudent);

        Course course = (Course) session.get(Course.class, 1);
        course.getStudents().add(newStudent);
        // session.update(course); This does not have any effect because the course is persistent anyway

        session.getTransaction().commit();
        session.close();
    }

Second direction (working fine - both the new course and the record in the middle table are saved in the database)

Session session = HibernateUtils.getSessionFactory().openSession();
    session.beginTransaction();
    {
        Course newCourse = new Course();
        newCourse.setName("Some course name");

        session.save(newCourse);

        Student student = (Student) session.get(Student.class, 1);
        student.getCourses().add(newCourse);

        session.getTransaction().commit();
        session.close();
    }

Here is the Student entity

@Entity(name = "Students")
public class Student {
    @Id
    @GeneratedValue
    @Column(name = "StudentId")
    private int id;

    @Column(name = "Name", nullable = false, length = 50)
    private String name;

    @Column(name = "Grade")
    private Double grade = null;

    @ManyToOne(cascade = CascadeType.PERSIST)
    @JoinColumn(name = "FacultyId", nullable = false)
    private Faculty faculty;

    @ManyToMany(cascade = CascadeType.PERSIST)
    @JoinTable(
        joinColumns = @JoinColumn(name = "StudentId"),
        inverseJoinColumns = @JoinColumn(name = "CourseId"))
    private Collection<Course> courses;

    public Student() {
        this.courses = new HashSet<Course>();
    }

    // Setters and Getters for all fields
}

And the Course entity

@Entity(name = "Courses")
public class Course {
    @Id
    @GeneratedValue
    @Column(name = "CourseId")
    private int id;

    @Column(name = "Name", nullable = false, length = 100)
    private String name;

    @ManyToMany(mappedBy = "courses", cascade = CascadeType.PERSIST)
    private Collection<Student> students;

    public Course() {
        this.students = new HashSet<Student>();
    }

    // Setters and Getters for all fields
}

See the following:

Cascade.ALL from non-owning entity side

I would also recommend encapsulating the add/remove operations. Have you getters for these collections return unmodifiable collections and force clients to use the following so the relationships are set correctly:

public class Course{
public void addStudent(Student student){
this.students.add(student);
student.getCourses().add(this);
}
}

public class Student{
public void addCourse(Course course){
this.courses.add(course);
course.students.add(this);
}
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM