“直接自我参照导致循环”杰克逊与继承

时间:2018-06-28 17:39:16

标签: java jpa inheritance jackson jaxb

我有一堂课,像这样:

@Entity
@Inheritance(strategy = InheritanceType.JOINED)
@Audited
@DiscriminatorColumn(name = "tipo_hito")
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(propOrder = { "idHito" })
@XmlRootElement(name = "Hito")
public abstract class Hito implements Ordenable {
    @Id
    @GeneratedValue(strategy= GenerationType.IDENTITY)
    @Column(name = "idhito", nullable = false)
    private Long idHito;

    public Long getIdHito() { return idHito; }

    public void setIdHito(Long idHito) { this.idHito = idHito; }
}

还有一个将类扩展到上方的类

@MappedSuperclass
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(propOrder = {..., "successors", "predecessors", ...})
@XmlRootElement(name = "HitoOrdenable")
public abstract class HitoOrdenable extends Hito {

    @XmlElement(name = "predecessors")
    @ManyToMany(fetch = FetchType.LAZY)
    @JoinTable(name = "succession", joinColumns = { @JoinColumn(name = "idpredecessor") }, inverseJoinColumns = { @JoinColumn(name = "idsuccessor") })
    private Set<Hito> predecessors;

    @XmlElement(name = "successors")
    @ManyToMany(fetch = FetchType.LAZY)
    @JoinTable(name = "succession", joinColumns = { @JoinColumn(name = "idsuccessor") }, inverseJoinColumns = { @JoinColumn(name = "idpredecessor") })
    private Set<Hito> successors;

    // More code...
}

现在,错误是当我尝试获取HitoOrdenable时出现的错误。因为例如我可以拥有:

Hito1
  Hito2-SuccessorOf1
  Hito3-SuccessorOf1
    Hito4-SuccessorOf3
Hito5
  Hito6-SuccessorOf5

因此,当我得到Hito1时,它具有后继者Hito2Hito3。但是当我得到Hito2时,它的前身是Hito1。因此,开始一个“无限循环”。

确切的错误是:

  

com.fasterxml.jackson.databind.JsonMappingException:直接   自参考导致循环(通过参考链:   ar.gob.buenosaires.esb.domain.message.ProyectoRespMsg [“ proyectos”]-> java.util.ArrayList [5]-> ar.gob.buenosaires.domain.Proyecto [“ obras”]-> org.hibernate。 collection.internal.PersistentBag [0]-> ar.gob.buenosaires.domain.Obra [“ hitos”]-> org.hibernate.collection.internal.PersistentBag [0]-> ar.gob.buenosaires.domain.HitoObra [ “ hitoOrdenable”])

我试图在predecessors中设置@JsonIgnore,但是它不起作用。

1 个答案:

答案 0 :(得分:1)

经过几天的尝试。我们发现的唯一解决方案是添加@JsonIgnoreProperties({"predecessors"})@JsonIdentityInfo(generator=ObjectIdGenerators.IntSequenceGenerator.class, property="idHitoAux")

HitoOrdenable.java

  @MappedSuperclass
  @XmlType(propOrder = {..., "successors", "predecessors", ...})
  @XmlAccessorType(XmlAccessType.FIELD)
  @JsonIgnoreProperties({ "predecessors" })
  @JsonIdentityInfo(generator=ObjectIdGenerators.IntSequenceGenerator.class, property="idHitoAux")

Hito.java

@Entity
@Inheritance(strategy = InheritanceType.JOINED)
@Audited
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(propOrder = { "idHito", "tipoHito"})
@JsonIgnoreProperties({"idHitoAux", "hibernateLazyInitializer", "handler"})
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.EXISTING_PROPERTY, visible = true, property = "tipoHito")
@JsonSubTypes({
        @JsonSubTypes.Type(name = "hito_obra", value = HitoObra.class),
        @JsonSubTypes.Type(name = "hito_proyecto", value = HitoProyecto.class)
})<

使用JsonIgnoreProperties可以防止继任者和前任者之间的无限循环,而对于@JsonIdentityInfo来说,这是因为如果我们使用"idHito"而不是"idHitoAux"(其等于idHito),则将idHito转换为null 。因此,借助"idHitoAux",Hibernate可以识别列表中的每个对象。

PD:在该解决方案之后,我们遇到了abstract class Hito反序列化的问题,因此我们的解决方案是添加@JsonSubTypes

问候!