4
votes

This is my sample schema and I have generated jpa entities in eclipse. I am using spring jpa repositories. I want to know if I need to create repository interface for student course table.

I am having doubt over addStudentCourse method of both student and course entity classes. List studentCourses will be always null for new entity, how can I fill student course table while registering student information in system i.e save method on studentRepository.

enter image description here

Student.java

@Entity
@NamedQuery(name="Student.findAll", query="SELECT s FROM Student s")
public class Student implements Serializable {
    private static final long serialVersionUID = 1L;

    @Id
    private long studentid;

    private String studentname;

    //bi-directional many-to-one association to StudentCourse
    @OneToMany(mappedBy="student")
    private List<StudentCourse> studentCourses;

    ........

    public StudentCourse addStudentCourse(StudentCourse studentCourse) {
        getStudentCourses().add(studentCourse);
        studentCourse.setStudent(this);

        return studentCourse;
    }

    public StudentCourse removeStudentCourse(StudentCourse studentCourse) {
        getStudentCourses().remove(studentCourse);
        studentCours.setStudent(null);

        return studentCourse;
    }

Course.java

@Entity
@NamedQuery(name="Course.findAll", query="SELECT c FROM Course c")
public class Course implements Serializable {
    private static final long serialVersionUID = 1L;

    @Id
    private long courseid;

    private String coursename;

    //bi-directional many-to-one association to StudentCourse
    @OneToMany(mappedBy="course")
    private List<StudentCourse> studentCourses;

    public StudentCourse addStudentCourse(StudentCourse studentCourse) {
        getStudentCourses().add(studentCourse);
        studentCourse.setCourse(this);

        return studentCourse;
    }

    public StudentCourse removeStudentCourse(StudentCourse studentCourse) {
        getStudentCourses().remove(studentCourse);
        studentCourse.setCourse(null);

        return studentCourse;
    }

StudentCourse.java

    @Entity
    @Table(name="STUDENT_COURSE")
    @NamedQuery(name="StudentCourse.findAll", query="SELECT s FROM StudentCourse s")
    public class StudentCourse implements Serializable {
        private static final long serialVersionUID = 1L;

        @EmbeddedId
        private StudentCoursePK id;

        private String status;

        //bi-directional many-to-one association to Course
        @ManyToOne
        @JoinColumn(name="COURSEID")
        private Course course;

        //bi-directional many-to-one association to Student
        @ManyToOne
        @JoinColumn(name="STUDENTID")
        private Student student;

       ...
}

StudentCoursePK.java

@Embeddable
public class StudentCoursePK implements Serializable {
    //default serial version id, required for serializable classes.
    private static final long serialVersionUID = 1L;

    @Column(insertable=false, updatable=false)
    private long studentid;

    @Column(insertable=false, updatable=false)
    private long courseid;

    ...
}
1

1 Answers

3
votes

If I understood your question correctly what you want to do is to be able to save a student from the save method in StudentRepository, and that this inserts/updates the student and also inserts/updates the join table.

Since the Student entity is not the owning side (it's mapped by "student" in StudentCourse), saving a Student will not trigger a save on StudentCourse. To do so you can add a cascade property the list for insert, update... or just for everything:

@OneToMany(mappedBy="student", cascade = CascadeType.ALL)
private List<StudentCourse> studentCourses = new ArrayList<StudentCourse>();

Then you could a method on your @Service class that looks like this:

@Transactional
public void enrollInCourse(Student student, Course course) {
    StudentCourse sc = new StudentCourse();
    sc.setStudent(student);
    sc.setCourse(course);
    sc.setStatus("Enrolled");
    student.getStudentCourses().add(sc);

    studentRepository.save(student);
}

This will also populate the StudentCourse table.

So there's no need for a repository, although if the cascade doesn't work as expected you could create one and save the StudentCourse entity yourself manually.

If this does not work you could try changing your mappings. For n-ary relationships or join tables with extra columns I always define the @ManytoOne relationships inside the @Embeddable class, and in the entity that represents the join table I define getters as @Transient to allow access to the mapped objects which are inside the embedded composite Id.

You can see an example here, and a blog post about this approach here.