首页 > 解决方案 > 如何使用关联实体处理 JPA 和 Hibernate 中的循环引用

问题描述

我有 3 个实体:RealestateRealtor和关联实体RealestateRealtor。一个房地产可以有多个房地产经纪人,反之亦然。多对多关系有一个带有特定 url 字段的额外实体 RealestateRealtor。

问题:如何使用@JsonIgnore、@JsonManaged 等创建工作参考...所以我可以请求一个拥有所有房地产子代的房地产经纪人,而在另一个请求中,一个拥有所有房地产经纪人子代的房地产经纪人不会削弱其中一个或成为由于忽略反序列化而未设置实体,因此无法保存。

房地产经纪人:

@Entity
@Table(name="realtor",uniqueConstraints={@UniqueConstraint(name = "uniquerealtor", columnNames = {"name", "streetname", "housenumber", "housenumberaddition", "cityname"})})
public class Realtor {

    @Id 
    @GeneratedValue(strategy=GenerationType.IDENTITY)
    private Integer idrealtor;
    
    @NotEmpty
    @Column(length = 100)
    private String name;
    
    @NotEmpty
    private String streetname;
    
    @NotNull
    private Integer housenumber;
    
    @Column(length = 5)
    private String housenumberaddition;
    
    @NotEmpty
    private String cityname;

    @OneToMany(mappedBy = "realtor", cascade = CascadeType.ALL)
    @JsonBackReference(value = "realestateref")
    private Set<RealestateRealtor> realestaterealtor = new HashSet<RealestateRealtor>();
    
    public Integer getIdrealtor() {
        return idrealtor;
    }

    public void setIdrealtor(Integer idrealtor) {
        this.idrealtor = idrealtor;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getStreetname() {
        return streetname;
    }

    public void setStreetname(String streetname) {
        this.streetname = streetname;
    }

    public Integer getHousenumber() {
        return housenumber;
    }

    public void setHousenumber(Integer housenumber) {
        this.housenumber = housenumber;
    }

    public String getHousenumberaddition() {
        return housenumberaddition;
    }

    public void setHousenumberaddition(String housenumberaddition) {
        this.housenumberaddition = housenumberaddition;
    }

    public String getCityname() {
        return cityname;
    }

    public void setCityname(String cityname) {
        this.cityname = cityname;
    }

    public Set<RealestateRealtor> getRealestaterealtor() {
        return realestaterealtor;
    }

    public void setRealestaterealtor(Set<RealestateRealtor> realestaterealtor) {
        this.realestaterealtor = realestaterealtor;
    }
}

房地产:

@Entity
@Table(name="realestate",uniqueConstraints={@UniqueConstraint(name = "uniquerealestate",columnNames = {"streetname" , "housenumber", "housenumberaddition", "cityname"})})
public class Realestate {

    @Id 
    @GeneratedValue(strategy=GenerationType.IDENTITY)
    private Integer idrealestate;
    
    @NotEmpty()
    private String streetname;
    
    @NotNull
    private Integer housenumber;
    
    @Column(length = 5)
    @javax.validation.constraints.NotNull
    private String housenumberaddition;
    
    @NotEmpty()
    private String cityname;
    
    @OneToMany(mappedBy = "realestate", cascade = CascadeType.ALL)
    @JsonManagedReference(value = "realestateref")
    private Set<RealestateRealtor> realestaterealtor = new HashSet<RealestateRealtor>();
    
    public Integer getIdrealestate() {
        return idrealestate;
    }

    public void setIdrealestate(Integer idrealestate) {
        this.idrealestate = idrealestate;
    }

    public String getStreetname() {
        return streetname;
    }

    public void setStreetname(String streetname) {
        this.streetname = streetname;
    }

    public Integer getHousenumber() {
        return housenumber;
    }

    public void setHousenumber(Integer housenumber) {
        this.housenumber = housenumber;
    }

    public String getHousenumberaddition() {
        return housenumberaddition;
    }

    public void setHousenumberaddition(String housenumberaddition) {
        this.housenumberaddition = housenumberaddition;
    }

    public String getCityname() {
        return cityname;
    }

    public void setCityname(String cityname) {
        this.cityname = cityname;
    }

    public Set<RealestateRealtor> getRealestaterealtor() {
        return realestaterealtor;
    }

    public void setRealestaterealtor(Set<RealestateRealtor> realestaterealtor) {
        this.realestaterealtor = realestaterealtor;
    }
}

房地产经纪人:

@Entity
@Table(name="realestaterealtor")
public class RealestateRealtor {
    
    @Id 
    @GeneratedValue(strategy=GenerationType.IDENTITY)
    private Integer idrealestaterealtor;
    
    @ManyToOne(cascade = CascadeType.ALL)
    @JoinColumn(name = "idrealestate")
    @JsonBackReference(value = "realestateref")
    private Realestate realestate;

    @ManyToOne(cascade = CascadeType.ALL)
    @JoinColumn(name = "idrealtor")
    private Realtor realtor;

    @Column(name = "realestateurl")
    private String realestateurl;

    @OneToMany(cascade = CascadeType.ALL)
    @JoinColumn(name = "idrealestaterealtor", nullable = true)
    private Set<Media> media = new HashSet<Media>();
    
    public Integer getIdrealestaterealtor() {
        return idrealestaterealtor;
    }

    public void setIdrealestaterealtor(Integer idrealestaterealtor) {
        this.idrealestaterealtor = idrealestaterealtor;
    }

    public Realestate getRealestate() {
        return realestate;
    }
    
    public void setRealestate(Realestate realestate) {
        this.realestate = realestate;
    }

    public Realtor getRealtor() {
        return realtor;
    }
    
    public void setRealtor(Realtor realtor) {
        this.realtor = realtor;
    }

    public String getRealestateurl() {
        return realestateurl;
    }

    public void setRealestateurl(String realestateurl) {
        this.realestateurl = realestateurl;
    }

    public Set<Media> getMedia() {
        return media;
    }

    public void setMedia(Set<Media> media) {
        this.media = media;
    }
}

发布的代码仅适用于Realestate请求,反之则不行。房地产经纪人的请求只显示自己而不是孩子。

我尝试了什么但没有成功:

  1. @JSonIgnore 仅在吸气剂上
  2. @JSonProperties ... allowGetters = false
  3. 具有唯一值的多个托管和反向引用

我没有尝试过 JSonViews、@JsonIdentityInfo 或自定义序列化程序

@Entity
@Table(name="realestate",uniqueConstraints={@UniqueConstraint(name = "uniquerealestate",columnNames = {"streetname" , "housenumber", "housenumberaddition", "cityname"})})
    @JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class,property = "idrealestate")
    public class Realestate {
@Entity
@Table(name="realtor",uniqueConstraints={@UniqueConstraint(name = "uniquerealtor", columnNames = {"name", "streetname", "housenumber", "housenumberaddition", "cityname"})})
    @JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class,property = "idrealtor")
    public class Realtor {

这导致了所有 Realtors 的 Realestate 的结果,但也导致了 Realtor 的所有 Realestate 和所有 Realtors 属于 Realesatet 的结果,最后一个“问题”在控制器中被解决,使其无效。房地产经纪人

标签: javajsonspringhibernate

解决方案


你可以使用,但如果你有一个事务结束的服务层和一个休息控制器层,在休息控制器层,你可以打破休息控制器代码JSonViews中的双向递归。

  • 在返回 type 的其余端点上Realestate,然后在其余控制器中,realState.getRealestaterealtor().forEach(item -> item.setRealState(null)
  • 在返回 type 的其余端点上RealestateRealtor,然后在其余控制器中,realestateRealtor.getRealestate().setRealestateRealtor(null)

推荐阅读