休眠中ManyToMany关系的无限递归
Posted
技术标签:
【中文标题】休眠中ManyToMany关系的无限递归【英文标题】:Infinite Recursion on ManyToMany relationship on hibernate 【发布时间】:2020-04-14 08:23:45 【问题描述】:我正在尝试在 Java 中创建双向 ManyToMany 模型,我在数据库中插入数据没有问题,但是当我尝试从这些表中检索数据时,它开始无限递归......我尝试了这个@中的解决方案987654321@ 但它们都不适合我,也许我把注释放在了错误的地方。
我需要找到 1 名学生以及分配给给定学生的课程是什么。
数据库
模型
学生
@Component
@Entity
@Table(name="Student")
public class Student
@Id
@Column(name="student_id")
@GeneratedValue(strategy=GenerationType.IDENTITY)
private Long id;
@Column(name="student_name")
private String name;
@Column(name="student_address")
private String address;
@Column(name="student_email")
private String email;
@Column(name="student_username")
private String username;
@Column(name="student_password")
private String password;
@JsonManagedReference
@OneToMany(fetch = FetchType.LAZY, mappedBy="pk.student")
private Set<StudentCourse> studentCourses;
public Student()
studentCourses = new HashSet<StudentCourse>(0);
public Long getId()
return id;
public void setId(Long id)
this.id = id;
public String getName()
return name;
public void setName(String name)
this.name = name;
public String getAddress()
return address;
public void setAddress(String address)
this.address = address;
public String getEmail()
return email;
public void setEmail(String email)
this.email = email;
public String getUsername()
return username;
public void setUsername(String username)
this.username = username;
public String getPassword()
return password;
public void setPassword(String password)
this.password = password;
public Set<StudentCourse> getCourses()
return studentCourses;
public void setCourses(Set<StudentCourse> studentCourses)
this.studentCourses = studentCourses;
课程
@Component
@Entity
@Table(name="Course")
public class Course
@Id
@Column(name="course_id")
@GeneratedValue(strategy=GenerationType.IDENTITY)
private Long id;
@Column(name="course_name")
private String name;
@Column(name="course_schedule")
private String schedule;
@ManyToOne
@JoinColumn(name = "teacher_id")
private Teacher teacher;
@JsonBackReference
@OneToMany(fetch = FetchType.LAZY, mappedBy="pk.course")
private Set<StudentCourse> studentCourses = new HashSet<StudentCourse>(0);
public Course()
public Teacher getTeacher()
return teacher;
public void setTeacher(Teacher teacher)
this.teacher = teacher;
public Long getId()
return id;
public void setId(Long id)
this.id = id;
public String getName()
return name;
public void setName(String name)
this.name = name;
public String getSchedule()
return schedule;
public void setSchedule(String schedule)
this.schedule = schedule;
public Set<StudentCourse> getStudentCourses()
return studentCourses;
public void setStudentCourses(Set<StudentCourse> studentCourses)
this.studentCourses = studentCourses;
学生课程
@Component
@Entity
@Table(name="Student_Course")
@AssociationOverrides(
@AssociationOverride(name = "pk.student",
joinColumns = @JoinColumn(name = "student_id")),
@AssociationOverride(name = "pk.course",
joinColumns = @JoinColumn(name = "course_id")) )
public class StudentCourse implements java.io.Serializable
@EmbeddedId
private StudentCourseId pk = new StudentCourseId();
public StudentCourseId getPk()
return pk;
public void setPk(StudentCourseId pk)
this.pk = pk;
@Transient
public Student getStudent()
return getPk().getStudent();
public void setStudent(Student student)
getPk().setStudent(student);
@Transient
public Course getCourse()
return getPk().getCourse();
public void setCourse(Course course)
getPk().setCourse(course);
StudentCourseId
@Embeddable
public class StudentCourseId implements java.io.Serializable
@ManyToOne
private Student student;
@ManyToOne
private Course course;
public Student getStudent()
return student;
public void setStudent(Student student)
this.student = student;
public Course getCourse()
return course;
public void setCourse(Course course)
this.course = course;
public boolean equals(Object o)
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
StudentCourseId that = (StudentCourseId) o;
if (student != null ? !student.equals(that.student) : that.student != null) return false;
if (course != null ? !course.equals(that.course) : that.course != null)
return false;
return true;
public int hashCode()
int result;
result = (student != null ? student.hashCode() : 0);
result = 31 * result + (course != null ? course.hashCode() : 0);
return result;
服务
//find a student by its ID
public Optional<Student> getStudentById(Long studentID) throws SQLException
return studentRepo.findById(studentID);
控制器
//find a student by its ID
@GetMapping("/findStudent/studentID")
public ResponseEntity<?> getStudentById(@PathVariable Long studentID)
student = sts.getStudentById(studentID).orElse(new Student());
return new ResponseEntity<>(student, HttpStatus.OK);
我的 Json 响应
在“studentCourses”下,我希望我有这个学生被分配到的课程列表,但我得到的只是同一个学生的无限递归......
提前致谢。
【问题讨论】:
请同时添加Teacher
实体类。当您获取Course
列表时,我怀疑这与Teacher
类有关。
尝试将@ManyToOne(fetch = FetchType.LAZY) 添加到StudentCourseId => Student 和Course。
我稍后再试试,谢谢!!
【参考方案1】:
使用@JsonIdentityInfo
让它工作,并没有改变类之间的关系。
课程
@Component
@JsonIdentityInfo(generator=ObjectIdGenerators.PropertyGenerator.class, property="id")
@Entity
@Table(name="Course")
public class Course
@Id
@Column(name="course_id")
@GeneratedValue(strategy=GenerationType.IDENTITY)
private Long id;
@Column(name="course_name")
private String name;
@Column(name="course_schedule")
private String schedule;
@ManyToOne
@JoinColumn(name = "teacher_id")
private Teacher teacher;
@OneToMany(fetch = FetchType.LAZY, mappedBy="pk.course")
private Set<StudentCourse> studentCourses = new HashSet<StudentCourse>(0);
public Course()
/*
@ManyToOne(cascade = CascadeType.PERSIST)
@JoinColumn(name="teacher_id")
public Teacher getTeacher()
return teacher;
*/
public Teacher getTeacher()
return teacher;
public void setTeacher(Teacher teacher)
this.teacher = teacher;
public Long getId()
return id;
public void setId(Long id)
this.id = id;
public String getName()
return name;
public void setName(String name)
this.name = name;
public String getSchedule()
return schedule;
public void setSchedule(String schedule)
this.schedule = schedule;
public Set<StudentCourse> getStudentCourses()
return studentCourses;
public void setStudentCourses(Set<StudentCourse> studentCourses)
this.studentCourses = studentCourses;
学生
@Component
@JsonIdentityInfo(generator=ObjectIdGenerators.PropertyGenerator.class, property="id")
@Entity
@Table(name="Student")
public class Student
@Id
@Column(name="student_id")
@GeneratedValue(strategy=GenerationType.IDENTITY)
private Long id;
@Column(name="student_name")
private String name;
@Column(name="student_address")
private String address;
@Column(name="student_email")
private String email;
@Column(name="student_username")
private String username;
@Column(name="student_password")
private String password;
@OneToMany(fetch = FetchType.LAZY, mappedBy="pk.student")
private Set<StudentCourse> studentCourses;
public Student()
studentCourses = new HashSet<StudentCourse>(0);
public Long getId()
return id;
public void setId(Long id)
this.id = id;
public String getName()
return name;
public void setName(String name)
this.name = name;
public String getAddress()
return address;
public void setAddress(String address)
this.address = address;
public String getEmail()
return email;
public void setEmail(String email)
this.email = email;
public String getUsername()
return username;
public void setUsername(String username)
this.username = username;
public String getPassword()
return password;
public void setPassword(String password)
this.password = password;
public Set<StudentCourse> getCourses()
return studentCourses;
public void setCourses(Set<StudentCourse> studentCourses)
this.studentCourses = studentCourses;
【讨论】:
以上是关于休眠中ManyToMany关系的无限递归的主要内容,如果未能解决你的问题,请参考以下文章
休眠 Spring:@ManyToMany DataIntegrityViolationException ConstraintViolationException
如何在 Kotlin 中使用 JPA ManyToMany 双向关系
注释 ConcurrentHashMap 时,在休眠中“非法尝试将非集合映射为 @OneToMany、@ManyToMany 或 @CollectionOfElements”