I managed to persist a many to many relationship on the child side, (mappedBy
), and it works just fine, as shown below:
Student Entity (Owner)
package com.main.manytomany.models;
import com.fasterxml.jackson.annotation.JsonIgnore;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import javax.persistence.*;
import java.util.HashSet;
import java.util.Set;
@Entity
@Table(name = "students")
@Getter
@Setter
@NoArgsConstructor
public class Student {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
@JsonIgnore
@ManyToMany(fetch = FetchType.LAZY, cascade = CascadeType.PERSIST)
@JoinTable
(
name = "students_courses",
joinColumns = {
@JoinColumn
(
name = "student_id",
referencedColumnName = "id",
nullable = false,
updatable = false
)
},
inverseJoinColumns = {
@JoinColumn
(
name = "course_id",
referencedColumnName = "id",
nullable = false,
updatable = false
)
}
)
private Set<Course> courses = new HashSet<>();
}
Course Entity (Child)
package com.main.manytomany.models;
import com.fasterxml.jackson.annotation.JsonIgnore;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import javax.persistence.*;
import java.util.HashSet;
import java.util.Set;
@Entity
@Table(name = "courses")
@Getter@Setter
@NoArgsConstructor
public class Course {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
@ManyToMany(mappedBy = "courses", fetch = FetchType.LAZY)
private Set<Student> students = new HashSet<>();
}
Student Service
package com.main.manytomany.services;
import com.main.manytomany.models.Student;
import com.main.manytomany.repositories.StudentRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
@Service
public class StudentService {
private final StudentRepository studentRepository;
@Autowired
public StudentService(StudentRepository studentRepository) {
this.studentRepository = studentRepository;
}
public List<Student> findAll() {
return this.studentRepository.findAll();
}
public Student getOneById(Long id) {
return this.studentRepository.getOne(id);
}
public void store(Student student) {
this.studentRepository.save(student);
}
}
Course Service
package com.main.manytomany.services;
import com.main.manytomany.models.Course;
import com.main.manytomany.models.Student;
import com.main.manytomany.repositories.CourseRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
import java.util.stream.Collectors;
@Service
public class CourseService {
private final CourseRepository courseRepository;
private final StudentService studentService;
@Autowired
public CourseService(CourseRepository courseRepository, StudentService studentService) {
this.courseRepository = courseRepository;
this.studentService = studentService;
}
public List<Course> findAll() {
return this.courseRepository.findAll();
}
public void store(Course course) {
course.getStudents()
.addAll(course
.getStudents()
.stream()
.map(s -> {
Student student = studentService.getOneById(s.getId());
student.getCourses().add(course);
return student;
}).collect(Collectors.toList()));
this.courseRepository.save(course);
}
}
Student Controller | Post Mapping
@PostMapping
public ResponseEntity<Void> create(@RequestBody Student student) {
this.studentService.store(student);
return new ResponseEntity<>(HttpStatus.CREATED);
}
Course Controller | Post Mapping
@PostMapping
public ResponseEntity<Void> create(@RequestBody Course course) {
this.courseService.store(course);
return new ResponseEntity<>(HttpStatus.CREATED);
}
Student List | Postman
Course List | Postman
Students_Courses | Pivot Table + Hibernate Query
How can I make it work in the owner table?
So that instead of the persistence running in the CourseService, it shall run, in the StudentService.
So that in Postman, I shall be writing something like that for insterting a student, along with his attached courses:
{
"name" : "John Doe",
"courses" : [
{
"id" : 1
},
{
"id" : 2
}
]
}
You need to cascade the changes (so pretty much the same way you did int the other direction) in the Course
entity:
@ManyToMany(mappedBy = "courses", fetch = FetchType.LAZY, cascade = {
CascadeType.PERSIST,
CascadeType.MERGE
})
private Set<Student> students = new HashSet<>();