javahibernate

StackoverflowError: I have a loop, but I dont know where and why


I know I have anywhere a loop but I dont know where and why. I try to add trainers to my course (Kurs). This is my code:

@EqualsAndHashCode( callSuper = false )
@Entity
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Kurs extends PanacheEntityBase implements Serializable {

    @Id
    @GeneratedValue( strategy = GenerationType.AUTO )
    private Long id;

    @Basic
    @Column(name = "name", nullable = false)
    private String name;

    @OneToMany(mappedBy = "kurs", fetch = FetchType.LAZY, cascade = CascadeType.ALL, orphanRemoval = true)
    private Set<Kurs2Trainer> trainers = new HashSet<>();

    public void addTrainer(Kursuser trainer) {
        // Create a Kurs2Trainer object
        Kurs2Trainer kurs2Trainer = new Kurs2Trainer();
        kurs2Trainer.setTrainer(trainer);
        kurs2Trainer.setKurs(this);

        // Add the Kurs2Trainer object to the trainers set
        this.trainers.add(kurs2Trainer);

        // Add this Kurs to the trainer's set
        trainer.getTrainerBei().add(kurs2Trainer);
    }
}

Kursuser:

@Entity
@Data
@EqualsAndHashCode( callSuper = false )
@NoArgsConstructor
@AllArgsConstructor
public class Kursuser extends PanacheEntityBase implements Serializable {

    @Id
    private Long id;

    @OneToOne( fetch = FetchType.LAZY )
    @MapsId
    private User user;

    /*
    Diese Person ist Trainer an den folgenden Kursen
     */
    @OneToMany( mappedBy = "trainer", fetch = FetchType.LAZY, cascade = CascadeType.ALL, orphanRemoval = true)
    private Set<Kurs2Trainer> trainerBei = new HashSet<>();
}

Kurs2Trainer:

@Entity
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Kurs2Trainer implements Serializable {

    @EmbeddedId
    private Kurs2TrainerID id = new Kurs2TrainerID();

    @MapsId("trainerId")
    @ManyToOne( fetch = FetchType.LAZY )
    @JoinColumn( name = "trainer_id" )
    private Kursuser trainer;

    @MapsId("kursId")
    @ManyToOne( fetch = FetchType.LAZY )
    @JoinColumn( name = "kurs_id" )
    private Kurs kurs;
}

Kurs2TrainerID:

@Data
@Embeddable
public class Kurs2TrainerID implements Serializable {
    @Column(name = "trainerId")
    private Long trainerId;
    @Column(name = "kursId")
    private Long kursId;
}

When I try to run this code:

private void addTrainerToKurs(User trainer, Kurs k){
    //Check if we have already the trainer in the course
    if ( CollectionUtils.isNotEmpty( k.getTrainers() ) ) {
        for(Kurs2Trainer kTrainer : k.getTrainers()){
            if(kTrainer.getId().getTrainerId().equals( trainer.getId())){
                return;
            }
        }
    }

    //We dont have this user in our course so add
    Kursuser trainerKursuser = kursuserService.getKursuser(trainer);
    k.addTrainer(trainerKursuser);
}

I get the following error message:

java.lang.StackOverflowError
    at at.tanzauswertung.portal.kurs.entities.Kursuser.$$_hibernate_read_id(Kursuser.java)
    at at.tanzauswertung.portal.kurs.entities.Kursuser.getId(Kursuser.java:25)
    at at.tanzauswertung.portal.kurs.entities.Kursuser.hashCode(Kursuser.java:19)
    at at.tanzauswertung.portal.kurs.entities.Kurs2Trainer.hashCode(Kurs2Trainer.java:11)
    at java.base/java.util.AbstractSet.hashCode(AbstractSet.java:124)

Please show me my mistake. Many thanks


Solution

  • You have a bidirectional relationship between Kurs and Kurs2Trainer. And it seems their hashCode method is trying to call each other, hence the loop.

    You should implement a custom hashCode and equals methods for your classes to avoid such recursion. It is fine to use their IDs instead, for example.

    This answer seems to be applicable to your case, including some native Hibernate mechanisms to implement that for you: https://stackoverflow.com/a/65018262/10119664