REST API 无限循环

REST API Infinite loop

我的 API 显示了地址字段的无限循环

当我插入@JsonIgnore、@JsonManagedReference 或@JsonBackReference 时 我可以清楚地看到一个结果,但我没有嵌套的地址字段。

我应该怎么做才能让那个地址字段也只有一个结果?

这些是我的主要实体:

1.Property

package com.realestate.petfriendly.entity;

import com.fasterxml.jackson.annotation.JsonBackReference;
import com.fasterxml.jackson.annotation.JsonIgnore;
import java.io.Serializable;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.OneToOne;
import javax.persistence.Table;
import lombok.Data;

@Entity
@Data
@Table(name = "property")
public class Property {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "id_property")
    private int id_property;
    @Column(name = "title")
    private String title;
    @Column(name = "type")
    private String type;
    @Column(name = "room")
    private String room;
    @Column(name = "price")
    private double price;

    @OneToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
    @JoinColumn(name = "address_id_address")
//  @JsonBackReference
    private Address address;

    @ManyToOne(fetch = FetchType.LAZY, optional = false)
    @JoinColumn(name = "user_id_user")
//  @JsonBackReference
    private User user;

} 
  1. 用户
package com.realestate.petfriendly.entity;

import com.fasterxml.jackson.annotation.JsonManagedReference;
import java.util.ArrayList;
import java.util.List;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.OneToMany;
import javax.persistence.OneToOne;
import javax.persistence.Table;
import lombok.Getter;
import lombok.Setter;

@Entity
@Getter
@Setter
@Table(name = "user")
class User {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "id_user")
    private int id_user;
    @Column(name = "username")
    private String username;
    @Column(name = "name")
    private String name;
    @Column(name = "lastname")
    private String lastname;
    @Column(name = "phone")
    private String phone;
    @Column(name = "notes")
    private String notes;

    @OneToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
    @JoinColumn(name = "user_address_id_user_address")
//  @JsonManagedReference
    private UserAddress userAddress;

    @OneToMany(fetch = FetchType.LAZY, cascade = CascadeType.ALL, mappedBy = "user")
//  @JsonManagedReference
    private List<Property> property = new ArrayList<>();

}
  1. 地址
package com.realestate.petfriendly.entity;

import com.fasterxml.jackson.annotation.JsonManagedReference;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.OneToOne;
import javax.persistence.Table;
import lombok.Getter;
import lombok.Setter;

@Entity
@Getter
@Setter
@Table(name="address")
class Address{

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "id_address")
    private int id_address;
    @Column(name = "city")
    private String city;
    @Column(name = "municipality")
    private String municipality;
    @Column(name = "place")
    private String place;
    @Column(name = "street")
    private String street;
    @Column(name = "house_number")
    private double house_number;
    
    @OneToOne(mappedBy = "address")
//  @JsonManagedReference
    private Property property;
} 

您在 属性 和地址 class 之间存在循环依赖。为了阻止无限 JSON 序列化循环,您可以在相关属性的一侧添加 @JsonIgnore 注释

您实际上在代码中找到了问题的解决方案,但关键注释被注释掉并位于错误的位置(根据您的要求)。解决此问题的方法之一是使用 @JsonManagedReference@JsonBackReference,如下所示:

@Entity
@Data
@Table(name = "property")
public class Property {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "id_property")
    private int id_property;
    @Column(name = "title")
    private String title;
    @Column(name = "type")
    private String type;
    @Column(name = "room")
    private String room;
    @Column(name = "price")
    private double price;

    @OneToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
    @JoinColumn(name = "address_id_address")
    @JsonManagedReference
    private Address address;

    @ManyToOne(fetch = FetchType.LAZY, optional = false)
    @JoinColumn(name = "user_id_user")
    @JsonBackReference
    private User user;
}
@Entity
@Getter
@Setter
@Table(name = "user")
class User {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "id_user")
    private int id_user;
    @Column(name = "username")
    private String username;
    @Column(name = "name")
    private String name;
    @Column(name = "lastname")
    private String lastname;
    @Column(name = "phone")
    private String phone;
    @Column(name = "notes")
    private String notes;

    @OneToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
    @JoinColumn(name = "user_address_id_user_address")
    private UserAddress userAddress;

    @OneToMany(fetch = FetchType.LAZY, cascade = CascadeType.ALL, mappedBy = "user")
    @JsonManagedReference
    private List<Property> property = new ArrayList<>();
}
@Entity
@Getter
@Setter
@Table(name="address")
class Address{

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "id_address")
    private int id_address;
    @Column(name = "city")
    private String city;
    @Column(name = "municipality")
    private String municipality;
    @Column(name = "place")
    private String place;
    @Column(name = "street")
    private String street;
    @Column(name = "house_number")
    private double house_number;
    
    @OneToOne(mappedBy = "address")
    @JsonBackReference
    private Property property;
}

请记住以下几点:

  • @JsonManagedReference 是关系的前向部分:正常序列化的部分。
  • @JsonBackReference是关系后面的部分:连载时会省略。

如果想对关系后面的部分有引用,可以使用@JsonIdentityInfo,如下:

@Entity
@Data
@Table(name = "property")
@JsonIdentityInfo(
  generator = ObjectIdGenerators.PropertyGenerator.class, 
  property = "id_property")
public class Property {
   (...)
}
@Entity
@Getter
@Setter
@Table(name = "user")
@JsonIdentityInfo(
  generator = ObjectIdGenerators.PropertyGenerator.class, 
  property = "id_user")
class User {
   (...)
}
@Entity
@Getter
@Setter
@Table(name="address")
@JsonIdentityInfo(
  generator = ObjectIdGenerators.PropertyGenerator.class, 
  property = "id_address")
class Address{
   (...)
}

您可以在以下在线资源中阅读有关这些和其他技术的更多信息:https://www.baeldung.com/jackson-bidirectional-relationships-and-infinite-recursion