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.