Spring Data JPA Hibernate fetching @OneToOne returns infinite loop of bidirectional entities

Viewed 324

I am working on saving an Employee record with its EmployeeIdCard bidirectional with @OneToOne and fetch = Lazy. While debugging my EmployeeRepository.findById() test case, I found this looping EmployeeIdCard.employee. enter image description here

Although this is not the case when it is returned into the EmployeeService but I want to understand what exactly is happening here. If I understand it correctly, this will loop infinitely. Is this normal? What could be causing this to happen and how to fix this? Below are the entities (removed other fields for simplicity).

// Employee.java
@Getter
@Setter
@ToString
@NoArgsConstructor
@AllArgsConstructor
@Entity(name = "Employee")
@Table(
  name = "employee",
  uniqueConstraints = {
    @UniqueConstraint(name = "employee_email_unique", columnNames = "email")
  }
)
public class Employee {

  @Id
  @Column(name = "id", updatable = false, nullable = false)
  private UUID id;

  @Column(name = "first_name", nullable = false, columnDefinition = "TEXT")
  private String firstName;

  @OneToOne(
    mappedBy = "employee",
    orphanRemoval = true,
    cascade = {CascadeType.PERSIST, CascadeType.MERGE, CascadeType.REMOVE},
    fetch = FetchType.LAZY
  )
  @ToString.Exclude
  @LazyToOne(NO_PROXY)
  private EmployeeIdCard employeeIdCard;

}
// EmployeeIdCard.java
@Getter
@Setter
@ToString
@NoArgsConstructor
@AllArgsConstructor
@Entity(name = "EmployeeIdCard")
@Table(
  name = "employee_id_card",
  uniqueConstraints = {
    @UniqueConstraint(name = "employee_id_card_number_unique", columnNames = "card_number")
  }
)
public class EmployeeIdCard {

  @Id
  @SequenceGenerator(
    name = "idcard_sequence",
    sequenceName = "idcard_sequence",
    allocationSize = 1
  )
  @GeneratedValue(strategy = SEQUENCE, generator = "idcard_sequence")
  @Column(name = "id", updatable = false, nullable = false)
  private Long id;

  @Column(name = "card_number", nullable = false, length = 8)
  private String cardNumber;

  @OneToOne(cascade = CascadeType.ALL, fetch = FetchType.LAZY)
  @JoinColumn(
    name = "employee_id",
    referencedColumnName = "id",
    foreignKey = @ForeignKey(name = "employee_id_card_employee_id_fk")
  )
  @ToString.Exclude
  @LazyToOne(NO_PROXY)
  private Employee employee;

}

EDIT 1: when fetching the parent entity (id), not saving

EDIT 2: The same behavior when setting up the parent-child before the save/fetch call. enter image description here

1 Answers

Just add this @JsonIgnore annotation on EmployeeIdCard Entity with Employee properties (Keep other annotation as like as before)

As:

class EmployeeIdCard {
  .
  .

@JsonIgnore
private Employee employee;

}
Related