I have to save entity Student with Course entity, but I have an extra Entity class StudentCourse to put starting date of the course and ending date. How to persist all data at once? This is my code until now:
@Entity
public class Student{
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "student_id")
private Integer id;
private String firstName;
private String lastName;
@OneToMany(mappedBy = "student")
Set<StudentCourse> studentCourses;
//have getter and setters and overridden hashCode() and equals
}
@Entity
public class StudentCourse {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
@ManyToOne
@JoinColumn(name = "student_id")
Student student;
@ManyToOne
@JoinColumn(name = "course_id")
Course course;
private Date startDate;
private Date endDate;
}
@Entity
public class Course {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "course_id")
private Integer id;
private String name;
private String description;
@OneToMany(mappedBy = "course")
Set<StudentCourse> studentCourses;
}
I need to save entity student with Set of courses, also I need to add the start date and end date into the StudentCourse table. I m using the JpaRepository interface.
CodePudding user response:
You need to add cascade
to @OneToMany
and @ManyToOne
annotations as follows:
@Entity
public class Student{
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "student_id")
private Integer id;
private String firstName;
private String lastName;
@OneToMany(mappedBy = "student", cascade = CascadeType.ALL)
Set<StudentCourse> studentCourses;
//have getter and setters and overridden hashCode() and equals
}
@Entity
public class StudentCourse {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
@ManyToOne
@JoinColumn(name = "student_id")
Student student;
@ManyToOne(cascade = CascadeType.ALL)
@JoinColumn(name = "course_id")
Course course;
private Date startDate;
private Date endDate;
}
This defines the set of cascadable operations that are propagated to the associated entity. The value cascade = ALL
is equivalent to cascade = { PERSIST, MERGE, REMOVE, REFRESH, DETACH }
. Additional details here.
Now with a Repository you can save Student
:
@Repository
public interface StudentRepository extends JpaRepository<Student, Integer> {
}
Once you have an instance of StudentRepository
you can call studentRepository.save(student)
(https://docs.spring.io/spring-data/commons/docs/current/api/org/springframework/data/repository/CrudRepository.html?is-external=true#save-S-).
CodePudding user response:
Be careful to use cascade
in the @OneToMany
annotations in your case. I suggest not to use it and follow these steps to persist them.
- Persist the
Student
andCourse
instance respectively.(I suggest useManyToOne
in the joint entity only). - Set up the relation between
Student
andCourse
in a newStudentCourse
(maybe use the nameCourseRegistration
is better) instance and persist it. NOTE, the student and course instance should be the persisted instance in the first step.
You can wrap the above steps in a transaction scope.
// dummy codes.
@Service
@Transactional
class SomeService {
public void saveCourseWithStudents(){
var savedCourse = courseRepository.save(course);
var savedStudent = studentRepository.save(student);
studentCourse.setCourse(savedCourse );
studentCourse.setStudent(savedStudent );
studentCourseRepsoitory.save(studentCourse);
}
}