we would like to implement many-to-many in 3 sperate entity class with Kotlin and SpringBoot. Here is our ERD.

We try to follow this tutoial: https://www.baeldung.com/jpa-many-to-many but it will cause a recurse call in our data information.
Here is our Entity class implementation:
@MappedSuperclass
abstract class BaseEntity {
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    open val uuid: UUID? = null
    open var updatedAt: Date? = null
    open var createdAt: Date? = null
    @PreUpdate
    fun updateUpdatedAt() {
        this.updatedAt = Date()
    }
    @PrePersist
    fun updateCreatedAt() {
        this.createdAt = Date()
    }
}
@Entity
@Table(name = "student")
open class StudentEntity: BaseEntity() {
    open var name: String? = null
    @OneToMany(mappedBy = "student", fetch = FetchType.EAGER) //EAGER fetch is used to test the data output
    open var attendance: MutableSet<AttendanceEntity> = mutableSetOf()
}
@Entity
@Table(name = "training")
open class TrainingEntity: BaseEntity() {
    open var name: String? = null
    @OneToMany(mappedBy = "training", fetch = FetchType.EAGER) //EAGER fetch is used to test the data output
    open var attendance: MutableSet<AttendanceEntity> = mutableSetOf()
}
@Entity
@Table(name = "attendance")
open class AttendanceEntity: BaseEntity(){
    @ManyToOne
    @JoinColumn(name = "student_id")
    open var student: StudentEntity? = null
    @ManyToOne
    @JoinColumn(name = "training_id")
    open var training: TrainingEntity? = null
    open var time: Date? = null
}
We use trainingRepository.findAll() to query all training for checking and the result:
[
    {
        //training
        "uuid": "ed5e7dd2-ae14-42f4-99d9-588fc2586209",
        "name": "training1"
        "updatedAt": "2022-07-31T09:50:00.000+00:00",
        "attendance": [
            {
                //attendance
                "uuid": "8b35bd45-7ab3-4ef1-af73-83d06ffd7543",
                "time": "2022-07-31T11:42:00.000+00:00",
                "student": {
                    //student
                    "uuid": "b5ae1031-011d-4378-8ae6-6055942e293b",
                    "name": "student1",
                    "attendance": [
                        {   
                            //attendance
                            "uuid": "0a9d5adb-cd7a-4c11-954a-132cbe6fc6eb",
                            "time": "2022-07-31T11:42:00.000+00:00",
                            "student": {
                                "uuid": "b5ae1031-011d-4378-8ae6-6055942e293b",
                                "name": "student1",
                                "attendance": [
                                    //recurse call attendance which we don't want
                                    ...
                                ]
                            }
                            //recurse call student which we don't want
                            ...
                        }
                    ]
                }
            }
        ]
    }
]
The expected result:
[
    {
        //training
        "uuid": "xxxx",
        "name": "training1"
        "updatedAt": "2022-07-31T09:50:00.000+00:00",
        "attendance": [
            {
                //attendance 1
                "uuid": "xxxx",
                "time": "2022-07-31T11:42:00.000+00:00",
                "student": {
                    //student 1
                    "uuid": "xxxx",
                    "name": "student1"
                }
                //attendance 2
                "uuid": "xxxx",
                "time": "2022-07-31T11:42:00.000+00:00",
                "student": {
                    //student 2
                    "uuid": "xxxx",
                    "name": "student2"
                }
                ...
            }
        ]
    }
]
How can we stop the recursion inside the student object class when using the EAGER fetch and what is the best practice of LAZY fetch and when to use it.
 
    