title: Infinite Recursion on ManyToMany relationship on hibernate
body: <p>I am trying to create a bidirectional ManyToMany model in Java, I have no problem inserting data in the database, but when I try to retrieve data from these tables it starts an infinite recursion... I tried the soluitons in this <a href="https://www.baeldung.com/jackson-bidirectional-relationships-and-infinite-recursion" rel="nofollow noreferrer">baeldung tutorial</a>
   but none of them worked for me, maybe I'm placing the annotations in the wrong place.</p>
  
  <p><strong><em>What I need is to find 1 student and what are the courses asigned to the given student.</em></strong></p>
  
  <p><b>Database</b></p>
  
  <p><a href="https://i.stack.imgur.com/y8nVN.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/y8nVN.png" alt="enter image description here"></a></p>
  
  <p><strong><em>Models</em></strong></p>
  
  <p><strong><em>Student</em></strong></p>
  
  <pre><code>@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&lt;StudentCourse&gt; studentCourses;
  
      public Student() {
          studentCourses = new HashSet&lt;StudentCourse&gt;(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&lt;StudentCourse&gt; getCourses() {
          return studentCourses;
      }
  
      public void setCourses(Set&lt;StudentCourse&gt; studentCourses) {
          this.studentCourses = studentCourses;
      }
  
  
  }
  </code></pre>
  
  <p><strong><em>Course</em></strong></p>
  
  <pre><code>@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&lt;StudentCourse&gt; studentCourses = new HashSet&lt;StudentCourse&gt;(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&lt;StudentCourse&gt; getStudentCourses() {
          return studentCourses;
      }
  
      public void setStudentCourses(Set&lt;StudentCourse&gt; studentCourses) {
          this.studentCourses = studentCourses;
      }
  
  
  }
  </code></pre>
  
  <p><strong><em>StudentCourse</em></strong></p>
  
  <pre><code>@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);
      }
  
  
  }
  </code></pre>
  
  <p><strong><em>StudentCourseId</em></strong></p>
  
  <pre><code>@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;
      }
  }
  </code></pre>
  
  <p><strong><em>Service</em></strong></p>
  
  <pre><code>//find a student by its ID
  public Optional&lt;Student&gt; getStudentById(Long studentID) throws SQLException{
  
      return studentRepo.findById(studentID);
  }
  </code></pre>
  
  <p><strong><em>Controller</em></strong></p>
  
  <pre><code>//find a student by its ID
  @GetMapping("/findStudent/{studentID}")
  public ResponseEntity&lt;?&gt; getStudentById(@PathVariable Long studentID){      
      student = sts.getStudentById(studentID).orElse(new Student());
      return new ResponseEntity&lt;&gt;(student, HttpStatus.OK);
  }
  </code></pre>
  
  <p><strong><em>My Json response</em></strong></p>
  
  <p><a href="https://i.stack.imgur.com/cIEDf.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/cIEDf.png" alt="enter image description here"></a></p>
  
  <p>Under "studentCourses" I wish I had the list of courses this student is assigned to, but all I get is the infinite recursion of the same student...</p>
  
  <p>Thanks in advance.</p>