Spring Data JPA:在两个方向上保持多对多的关系
Spring Data JPA : persist a many to may relationship in both directions
我设法在子端保持多对多关系,(mappedBy
),它工作得很好,如下所示:
学生实体(所有者)
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<>();
}
课程实体(儿童)
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<>();
}
学生服务
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);
}
}
课程服务
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);
}
}
学生管理员 | Post映射
@PostMapping
public ResponseEntity<Void> create(@RequestBody Student student) {
this.studentService.store(student);
return new ResponseEntity<>(HttpStatus.CREATED);
}
课程管理员 | Post映射
@PostMapping
public ResponseEntity<Void> create(@RequestBody Course course) {
this.courseService.store(course);
return new ResponseEntity<>(HttpStatus.CREATED);
}
学生名单 | Post男人
课程列表 | Post男人
Students_Courses | Pivot Table + Hibernate 查询
如何让它在所有者中工作 table?
因此,与其在 CourseService 中持久化 运行ning,不如在 StudentService 中 运行、。
因此,在 Postman 中,我将写一些类似的东西来指导学生,连同他的附加课程:
{
"name" : "John Doe",
"courses" : [
{
"id" : 1
},
{
"id" : 2
}
]
}
您需要在 Course
实体中级联更改(与您在另一个方向上所做的方式几乎相同):
@ManyToMany(mappedBy = "courses", fetch = FetchType.LAZY, cascade = {
CascadeType.PERSIST,
CascadeType.MERGE
})
private Set<Student> students = new HashSet<>();
而不是使用 - mappedBy
这很好用(如果我们想保留一个实体作为父实体),您可以在两个表中使用 @JoinTable
并定义相应的方法来保存数据。
因此,更改下面的映射和 StudentService
中的 store
方法来保存课程是可行的。
@JsonIgnore
@ManyToMany(fetch = FetchType.LAZY, cascade = CascadeType.PERSIST)
@JoinTable
(
name = "students_courses",
joinColumns = {
@JoinColumn
(
name = "course_id",
referencedColumnName = "id",
nullable = false,
updatable = false
)
},
inverseJoinColumns = {
@JoinColumn
(
name = "student_id",
referencedColumnName = "id",
nullable = false,
updatable = false
)
}
)
private Set<Student> students = new HashSet<>();
示例:
@ManyToMany(fetch=FetchType.LAZY,cascade={CascadeType.PERSIST,CascadeType.DETACH,CascadeType.REFRESH,CascadeType.MERGE})
@JoinTable(name="course_student", joinColumns=@JoinColumn(name="course_id"), inverseJoinColumns=@JoinColumn(name="student_id"))
private List<Student> students;
@ManyToMany(fetch=FetchType.LAZY,cascade={CascadeType.PERSIST,CascadeType.DETACH,CascadeType.REFRESH,CascadeType.MERGE})
@JoinTable(name="course_student", joinColumns=@JoinColumn(name="student_id"), inverseJoinColumns=@JoinColumn(name="course_id"))
private List<Course> courses;
我设法在子端保持多对多关系,(mappedBy
),它工作得很好,如下所示:
学生实体(所有者)
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<>();
}
课程实体(儿童)
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<>();
}
学生服务
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);
}
}
课程服务
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);
}
}
学生管理员 | Post映射
@PostMapping
public ResponseEntity<Void> create(@RequestBody Student student) {
this.studentService.store(student);
return new ResponseEntity<>(HttpStatus.CREATED);
}
课程管理员 | Post映射
@PostMapping
public ResponseEntity<Void> create(@RequestBody Course course) {
this.courseService.store(course);
return new ResponseEntity<>(HttpStatus.CREATED);
}
学生名单 | Post男人
课程列表 | Post男人
Students_Courses | Pivot Table + Hibernate 查询
如何让它在所有者中工作 table?
因此,与其在 CourseService 中持久化 运行ning,不如在 StudentService 中 运行、。
因此,在 Postman 中,我将写一些类似的东西来指导学生,连同他的附加课程:
{
"name" : "John Doe",
"courses" : [
{
"id" : 1
},
{
"id" : 2
}
]
}
您需要在 Course
实体中级联更改(与您在另一个方向上所做的方式几乎相同):
@ManyToMany(mappedBy = "courses", fetch = FetchType.LAZY, cascade = {
CascadeType.PERSIST,
CascadeType.MERGE
})
private Set<Student> students = new HashSet<>();
而不是使用 - mappedBy
这很好用(如果我们想保留一个实体作为父实体),您可以在两个表中使用 @JoinTable
并定义相应的方法来保存数据。
因此,更改下面的映射和 StudentService
中的 store
方法来保存课程是可行的。
@JsonIgnore
@ManyToMany(fetch = FetchType.LAZY, cascade = CascadeType.PERSIST)
@JoinTable
(
name = "students_courses",
joinColumns = {
@JoinColumn
(
name = "course_id",
referencedColumnName = "id",
nullable = false,
updatable = false
)
},
inverseJoinColumns = {
@JoinColumn
(
name = "student_id",
referencedColumnName = "id",
nullable = false,
updatable = false
)
}
)
private Set<Student> students = new HashSet<>();
示例:
@ManyToMany(fetch=FetchType.LAZY,cascade={CascadeType.PERSIST,CascadeType.DETACH,CascadeType.REFRESH,CascadeType.MERGE})
@JoinTable(name="course_student", joinColumns=@JoinColumn(name="course_id"), inverseJoinColumns=@JoinColumn(name="student_id"))
private List<Student> students;
@ManyToMany(fetch=FetchType.LAZY,cascade={CascadeType.PERSIST,CascadeType.DETACH,CascadeType.REFRESH,CascadeType.MERGE})
@JoinTable(name="course_student", joinColumns=@JoinColumn(name="student_id"), inverseJoinColumns=@JoinColumn(name="course_id"))
private List<Course> courses;