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

JPA many-to-many relationship causing infinite recursion and stack overflow error

我正在开发一个 EclipseLink 项目,其中一个用户可以 "follow" 另一个用户,就像在社交媒体网站上一样。我设置了一个 User 实体(引用一个名为 users 的 table),它有一个列表 "followers"(关注该用户的用户)和另一个列表 "following"(用户关注的用户)。该关系在名为 followers 的单独 table 中定义,其中包含关注用户 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() 时,我收到一堆控制台垃圾邮件,最终导致 WhosebugException:

com.fasterxml.jackson.databind.JsonMappingException: Infinite recursion 
(WhosebugError) (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)
...

如果我应该提供更多堆栈跟踪,请告诉我。有什么提示吗?

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

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

首先,您需要向两个实体(不是关系实体)添加此注释:

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

其中 "relationClass" 是关系的 class 的 List/Set 的名称:

例如:

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

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

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

希望对大家有所帮助!

我觉得之前回答的问题是注解的封装问题。在文章中http://www.baeldung.com/jackson-bidirectional-relationships-and-infinite-recursion @JsonManagedReference 和@JsonBackReference 工作正常。

但包裹应该是 com.fasterxml.jackson.annotation .

有时可能导入了其他包也无法解决问题。

另外添加

import com.fasterxml.jackson.annotation.JsonIdentityInfo;

@JsonIdentityInfo(
        generator = ObjectIdGenerators.PropertyGenerator.class,
        property = "id")

在模型的 class 定义工作正常之前。

public class A {
  private String name;
  
  @JsonIgnoreProperties(value = "linkToA") // remove field to avoid loop
  private B linkToB;
}

public class B {
  private String name;
  
  @JsonIgnoreProperties(value = "linkToB") // remove field to avoid loop
  private A linkToA;
}

您还可以使用 lombok 的 EqualsAndHashcode 注释,如下所示。

@EqualsAndHashcode(不包括 ={"following"}) public class 用户{}