使用Jackson JSON和Hibernate JPA出现无限递归问题(又一个)。

7
我找到了很多关于这个问题的资源,比如这个 - Jackson JSON和Hibernate JPA无限递归问题。我尝试实现了那里描述的各种建议(包括基本的@JsonIgnore),但是没有任何效果,无论我尝试什么都只能得到无限递归错误。我认为我的设置相当相似/典型,但显然有些问题,因为尽管使用了@JsonManagedReference、@JsonBackReferencere和@JsonIdentityInfo注释,我仍然会收到错误信息。
我的表是“exchange”和“stock”,它们之间有一个多对多的关系,并且我一直在通过ExchangeEndpoint进行测试。我确认如果我完全从“exchange”实体中删除“stock”,服务就可以正常工作,但出于某种原因,json注释似乎没有任何影响。下面是我认为基于前述Jackson JSON和Hibernate JPA无限递归问题中第二个(但更流行)答案的解决方案。
Exchange.java
@Entity
@Table(name = "exchange", schema = "public")
@XmlRootElement
@JsonIdentityInfo(generator=ObjectIdGenerators.IntSequenceGenerator.class, property="@id")
public class Exchange implements java.io.Serializable {
...
    @OneToMany(fetch = FetchType.LAZY, mappedBy = "exchange")
    @JsonManagedReference
    public Set<Stock> getStocks() {
        return this.stocks;
    }
...

Stock.java

@Entity
@Table(name = "stock", schema = "public")
@XmlRootElement
@JsonIdentityInfo(generator=ObjectIdGenerators.IntSequenceGenerator.class, property="@id")
public class Stock implements java.io.Serializable {
...
    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "exchangeid", nullable = false)
    @JsonBackReference
    @JsonIgnore
    public Exchange getExchange() {
        return this.exchange;
    }
...

ExchangeEndpoint.java

@Stateless
@Path("/exchanges")
public class ExchangeEndpoint {
    @PersistenceContext(unitName = "postgresql-ss4")
    private EntityManager em;
...
    @GET
    @Produces("application/json")
    public List<Exchange> listAll(@QueryParam("start") Integer startPosition,
            @QueryParam("max") Integer maxResult) {
        TypedQuery<Exchange> findAllQuery = em
                .createQuery(
                        "SELECT DISTINCT e "
                        + "FROM Exchange e "
                        + "LEFT JOIN FETCH e.stocks "
                        + "ORDER BY e.exchangeid",
                        Exchange.class);
        if (startPosition != null) {
            findAllQuery.setFirstResult(startPosition);
        }
        if (maxResult != null) {
            findAllQuery.setMaxResults(maxResult);
        }
        final List<Exchange> results = findAllQuery.getResultList();
        return results;
    }

编辑:

以下是一些错误输出,以确保我没有误解什么;

15:35:16,406 错误 [org.jboss.resteasy.resteasy_jaxrs.i18n] (http-/0.0.0.0:8080-1) RESTEASY000100: 执行 GET /exchanges/ 失败: org.jboss.resteasy.spi.WriterException: org.codehaus.jackson.map.JsonMappingException: 无限递归 (StackOverflowError)(通过引用链: net.hb.forge2RestServices.model.Exchange["stocks"]->org.hibernate.collection.internal.PersistentSet[0]->net.hb.forge2RestServices.model.Stock["exchange"]->net.hb.forge2RestServices.model.Exchange["stocks"]->org.hibe ... ... Exchange["stocks"]->org.hibernate.collection.internal.PersistentSet[0]->net.hb.forge2RestServices.model.Stock["exchange"]->net.hb.forge2RestServices.model.Exchange["stocks"]) at org.jboss.resteasy.core.ServerResponse.writeTo(ServerResponse.java:262)

请告诉我还能提供什么其他信息来帮助解释我的困境。感谢。

4个回答

3
问题是你有对 Stock 的引用,而从 Stock 返回,你又有对 Exchange 的引用。因此,JSON 先到达股票,再返回到 Exchange,然后对于 Exchange,它将生成所有的 Stock 等等。
为了打破这个循环,最好在引用父对象的字段上加上 JsonIgnore 注解 - 在这种情况下,它是 Stock.exchange 字段(或该字段的 getter)。

我尝试以几种不同的方式添加JsonIgnore注释,但似乎没有任何行为上的差异。我已更新原始问题并附加了其中一种方法,但我还尝试替换JsonBackReference并将注释移到字段定义(而不是Getter),但似乎获得相同的结果。是否有可能这些注释被否定了? - swv

3
这种问题如果您不通过REST公开JPA实体,则更容易避免。您应该考虑在REST端使用DTO,并通过手动编写映射器或使用MapStruct生成映射器来将实体映射到DTO及反向操作。额外的好处是可以避免安全问题。

MapStruct 确实很有趣。我一直希望这个项目不会变得足够复杂,以至于必须添加像这样的另一个层次,但我可以想象到将有大量其他项目需要它。感谢您提供的参考。 - swv

2

看起来问题在于导入。我不确定为什么,但是org.codehaus.jackson.annotate.JsonIgnore适用于我,而com.fasterxml.jackson.annotation.JsonIgnore不适用。


2
使用 @JsonManagedReference,@JsonBackReference。
public class User {
   public int id;
   public String name;

   @JsonBackReference
   public List<Item> userItems;
}


public class Item {
    public int id;
    public String itemName;

    @JsonManagedReference
    public User owner;
}

请注意:
@JsonManagedReference 是引用关系的前半部分 - 会正常序列化。
@JsonBackReference 是引用关系的后半部分 - 会在序列化时被省略。

http://www.baeldung.com/jackson-bidirectional-relationships-and-infinite-recursion


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接