我试图创建同一实体类型的父子关系。我面临的一个问题是,当尝试执行GET请求以检索子级不为空的实体时,我将从看起来像无限循环的地方获得堆栈溢出错误。环顾四周后,我发现了一个修复方法,只需在实体类的父字段中添加一个@JsonIgnore。我的问题是为什么这能解决这个问题?一开始是什么问题?

@Entity
@Table(name = "trash")
public class Trash {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @NotBlank
    private String username;

    @NotBlank
    private String message;

    private Long likes;

    @ManyToOne(cascade = CascadeType.ALL,fetch = FetchType.LAZY)
    @JsonIgnore
    private Trash parent;

    @OneToMany(cascade = CascadeType.ALL, mappedBy="parent", orphanRemoval=true, fetch = FetchType.LAZY)
    private Collection<Trash> children;

这是我收到的错误
2019-07-19 10:29:55.867 ERROR 14156 --- [nio-8080-exec-2] o.a.c.c.C.[.[.[/].[dispatcherServlet]    : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is org.springframework.http.converter.HttpMessageNotWritableException: Could not write JSON: Infinite recursion (StackOverflowError); nested exception is com.fasterxml.jackson.databind.JsonMappingException: Infinite recursion (StackOverflowError) (through reference chain: com.example.litter.model.Trash["parent"]->com.example.litter.model.Trash$HibernateProxy$lBPNIlf1["children"]->org.hibernate.collection.internal.PersistentBag[0]->com.example.litter.model.Trash["parent"]->com.example.litter.model.Trash$HibernateProxy$lBPNIlf1["children"]->org.hibernate.collection.internal.PersistentBag[0]->com.example.litter.model.Trash["parent"]->com.example.litter.model.Trash$HibernateProxy$lBPNIlf1["children"]->org.hibernate.collection.internal.PersistentBag[0]->com.example.litter.model.Trash["parent"]->com.example.litter.model.Trash$HibernateProxy$lBPNIlf1["children"]->org.hibernate.collection.internal.PersistentBag[0]->com.example.litter.model.Trash["parent"]->com.example.litter.model.Trash$HibernateProxy$lBPNIlf1["children"]->org.hibernate.collection.internal.PersistentBag[0]->com.example.litter.model.Trash["parent"]->com.example.litter.model.Trash$HibernateProxy$lBPNIlf1["children"]->org.hibernate.collection.internal.PersistentBag[0]->com.example.litter.model.Trash["parent"]-
repeats for awhile....
>com.example.litter.model.Trash$HibernateProxy$lBPNIlf1["children"]->org.hibernate.collection.internal.PersistentBag[0]->com.example.litter.model.Trash$HibernateProxy$lBPNIlf1["children"]->org.hibernate.collection.internal.PersistentBag[0]->com.example.litter.model.Trash["parent"])] with root cause

java.lang.StackOverflowError: null

最佳答案

例外情况说明:
无法写入JSON:无限递归(StackOverflowError);嵌套异常为com.fasterxml.jackson.databind.JsonMappingException:无限递归(StackOverflowError)
(通过参考链:
>com.example.little.model.Trash[“父级”]-
>com.example.little.model.Trash$HibernateProxy$lBPNIlf1[“子项”]-
>org.hibernate.collection.internal.PersistentBag[0]>com.example.little.model.Trash[“父级”]-
>com.example.little.model.Trash$HibernateProxy$lBPNIlf1[“子项”]-
>org.hibernate.collection.internal.PersistentBag[0]-
>com.example.little.model.Trash[“父级”]-
>com.example.little.model.Trash$HibernateProxy$lBPNIlf1[“子项”]-
>org.hibernate.collection.internal.PersistentBag[0]-
>com.example.little.model.Trash[“父级”]-
所以为了。。。
字段序列化触发自身的字段序列化
触发parent字段序列化,以便。。。
这看起来很抽象,下面是一个具体的例子。
假设这三个children实例:一个父对象有两个子对象。
垃圾桶-1(儿童=2,3)
垃圾箱-2(父级:1)
垃圾箱-3(父级:1)
假设您想要序列化parent(父项)。
以下是杰克逊的进展:
1)Jackson试图序列化Trash字段,我们感兴趣的Trash-1字段(Trash-1children)。
所以它启动了Trash-2序列化。
2)但是要序列化Trash-3,Jackson还需要序列化它的字段,即children字段!
3)我们回到第一步。
它一直持续到递归太重要而Jackson阻止了你。
通过用Trash-2注释parentTrash-1,您要求Jackson跳过两个序列化中的一个,从而中断递归。
例如,在parent上,它将给出:
1)Jackson试图序列化children字段,我们感兴趣的@JsonIgnore字段(parentTrash-1)。
所以它启动了children序列化。
2)Trash-2被序列化(不需要字段序列化)。
2)Trash-3被序列化(不需要字段序列化)。
一切都结束了。

09-27 17:51