SpringBoot Data Jpa 級聯查詢死循環

  1. 踩坑紀錄

踩坑紀錄

使用SpringBoot data JPA使用@OneToOne/@OneToMnay查詢數據時死循環,報錯內容如下:

java.lang.StackOverflowError at java.util.Date.getYear(Date.java:651) at java.sql.Timestamp.toString(Timestamp.java:279)....

解決方案:

使用debug查詢後發現是查詢時發生死循環

image-20230421172122048

經過測試後,發現級聯時會在兩個地方產生死循環

1.實體類的toString()方法中包含對級聯對象的輸出,代碼中調用了實體類的toString()方法。

2.接口查詢或轉為Json返回前端時,對實體對象進行序列化。

  • 解決實體類的toString()方法中包含對級聯對象的輸出 (查詢SQL時報錯)

    • 方法一:在其中一個實體對象修改toString(),將級聯對象移除

      @Entity
      @Getter
      @Setter
      @Table(name = "t_company")
      public class Company {
      @Id
      @GeneratedValue
      private int companyId;
      private String companyName;
      private String companyTel;
      private String companyAddress;
      @OneToOne(mappedBy = "company")
      private Good good;
      
      @Override
      public String toString() {
          return "Company{" +
                  "companyId=" + companyId +
                  ", companyName='" + companyName + '\'' +
                  ", companyTel='" + companyTel + '\'' +
                  ", companyAddress='" + companyAddress + '\'' +
                  '}';
      }
      }
      
    • 方法二:使用lombok裡面提供的注釋@ToString.Exclude
      ```java
      @Entity
      @Data
      @Table(name = “t_company”)
      public class Company {
      @Id
      @GeneratedValue
      private int companyId;
      private String companyName;
      private String companyTel;
      private String companyAddress;
      @OneToOne(mappedBy = “company”)
      @ToString.Exclude
      private Good good;

}


* 解決轉為Json返回前端時,對實體對象進行序列化死循環問題
  * 在其中一個級聯對象中使用`@JsonIgnore`或`@JsonIgnoreProperties`
```java
@Entity
@Data
@Table(name = "t_company")
public class Company {
    @Id
    @GeneratedValue
    private int companyId;
    private String companyName;
    private String companyTel;
    private String companyAddress;
    @OneToOne(mappedBy = "company")
    @JsonIgnore
    @ToString.Exclude
    private Good good;

}

不會產生死循環的代碼如下:

@Entity
@Data
@Table(name = "t_good")
public class Good {
    @Id
    @GeneratedValue
    private int gId;
    private String lineId;
    private Date pDate;
    @OneToOne(optional = false, cascade = CascadeType.ALL)
    @JoinColumn(name = "companyId")
    //@JsonIgnoreProperties("good") 忽略company中的good屬性
    private Company company;
    private String lineName;
    private String lineType;
    private int totalCount;
    private BigDecimal unitPrice;
    private BigDecimal totalPrice;
    private BigDecimal totalProfit;
}

@Entity
@Data
@Table(name = "t_company")
public class Company {
  @Id
  @GeneratedValue
  private int companyId;
  private String companyName;
  private String companyTel;
  private String companyAddress;
  @OneToOne(mappedBy = "company")
  @JsonIgnore //忽略good實體的查詢,避免死循環
  @ToString.Exclude
  private Good good;

}

轉載請注明來源,歡迎對文章中的引用來源進行考證,歡迎指出任何有錯誤或不夠清晰的表達。可以郵件至 b8954008@gmail.com