JPA多对多关系导致无限递归和堆栈溢出错误

时间:2017-04-18 20:11:28

标签: java postgresql jpa eclipselink

我正在开发一个EclipseLink项目,其中一个用户可以"关注"另一个可以在社交媒体网站上完成。我设置了一个User实体(引用一个名为users的表),其中有一个"关注者列表" (关注该用户的用户)和另一个"以下" (用户正在关注的用户)。该关系在名为followers的单独表格中定义,该表格包含所关注用户的ID(user_id)和以下用户ID(follower_id)的列。

我的用户模型如下所示:

@Entity
@Table(name = "users")
@NamedQuery(name = "User.findAll", query = "SELECT u FROM USER u")
public class User {
    // other attributes
    @ManyToMany(fetch = FetchType.LAZY)
    @JoinTable(name = "follower", joinColumns = @JoinColumn(
        name = "user_id", referencedColumnName = "id"),
    inverseJoinColumns = @JoinColumn(
        name = "follower_id", referencedColumnName = "id"))
    private List<User> followers;

    @ManyToMany(mappedBy = "followers")
    private List<User> following;

    // other getters and setters
    public List<User> getFollowers() {
        return this.followers;
    }

    public List<User> getFollowing() {
        return this.following;
    }
}

getFollowers()方法似乎工作正常,但是当调用getFollowing()时,我得到一堆控制台垃圾邮件,最终导致StackOverflowException:

com.fasterxml.jackson.databind.JsonMappingException: Infinite recursion 
(StackOverflowError) (through reference chain: 
org.eclipse.persistence.indirection.IndirectList[0]-
>org.myproject.model.User["followers"]-
>org.eclipse.persistence.indirection.IndirectList[0]-
>org.myproject.model.User["following"]-
...
at com.fasterxml.jackson.databind.ser.std.BeanSerializerBase
.serializeFields(BeanSerializerBase.java:518)
at com.fasterxml.jackson.databind.ser.BeanSerializer.serialize
(BeanSerializer.java:117)
at com.fasterxml.jackson.databind.ser.impl.IndexedListSerializer
.serializeContents(IndexedListSerializer.java:94)
at com.fasterxml.jackson.databind.ser.impl.IndexedListSerializer
.serializeContents(IndexedListSerializer.java:21)
...

如果我应该提供更多的堆栈跟踪,请告诉我。任何提示?

2 个答案:

答案 0 :(得分:6)

每次有@OneToMany(一个集合)时,你需要向它添加@JsonIgnore,否则会导致无限循环,导致堆栈溢出异常,因为它一直在父节点之间查找(一方)和孩子(多方) 有关处理此类问题的详细信息,请查看此优秀文章http://www.baeldung.com/jackson-bidirectional-relationships-and-infinite-recursion

答案 1 :(得分:0)

我尝试了在网络上找到的所有内容,但没有成功。没有任何注释。 但是在与这个问题进行了激烈的斗争之后,我找到了解决方案。

您需要在两个实体(不是关系实体)中添加此注释的第一点:

@JsonIgnoreProperties({"hibernateLazyInitializer", "handler", "relationClass"})
public class YourClass { ...
}

其中“ relationClass”是关系的类的列表/集合的名称:

例如:

  @OneToMany(mappedBy = "yourClass", cascade = CascadeType.ALL, fetch = FetchType.LAZY,  orphanRemoval = true)
    private Set<RelationClass> relationClass;

您还需要在注释中指定“ hibernateLazyInitializer”,“ handler”,否则会导致序列化问题。

在此之后,如果您看到定义关系表的表,并且在那里将看到行,并且JSON响应中将不再有任何循环。因此,我认为最好的解决方案是为关系表创建一个存储库并从那里访问数据。

希望它将对某人有所帮助!