【问题标题】:How to deal with circular references in JPA and Hibernate with associative entity如何使用关联实体处理 JPA 和 Hibernate 中的循环引用
【发布时间】:2020-07-21 07:35:09
【问题描述】:

我有 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 请求,反之则不行。 Realtor 请求只显示自己,而不是子项。

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

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

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

  • 我添加了@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 的结果,最后一个“问题”已在控制器中解决,使其无效。房地产经纪人

【问题讨论】:

  • @JSonIdentityInfo 结合答案修复了大部分部分。

标签: java json spring hibernate


【解决方案1】:

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

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

【讨论】:

  • 我已经尝试过这个并且它有效。我还添加了@JSonIdentityInfo。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-01-08
  • 2019-07-18
  • 1970-01-01
  • 1970-01-01
  • 2015-09-27
  • 2020-07-12
  • 2021-09-02
相关资源
最近更新 更多