JPA多一到许多的关系,导致无限递归和堆叠溢出错误



我正在研究一个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()称为我会得到一堆控制台垃圾邮件,该垃圾邮件最终在stackoverflowExcept中:

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)
...

请让我知道我是否应该提供更多堆栈跟踪。有提示吗?

每次您拥有@OneToMany(集合(时,您需要向其添加@JsonIgnore,否则会导致无限循环,从而导致堆栈溢出异常,因为它会一直在父母之间查找(一侧(和孩子(许多侧(有关解决此类问题的更多信息,请查看此出色的文章http://www.baeldung.com/jackson-bidirectional-relationships-and-and-infinite-recursion

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;
}

我尝试了我在网络中发现的所有内容,但它不起作用。没有任何注释。但是我在与这个问题进行了巨大的战斗后找到了解决方案。

第一点您需要添加到两个实体(而不是关系一个实体(:

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

其中"关系类"是您类关系的列表/集合的名称:

例如:

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

您还需要指定注释中的" HibernatelazyInitializer","处理程序",或者会导致序列化问题。

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

希望它能帮助某人!

我认为先前答案中的问题是注释的包。在文章中@jsonmanagedReference和@jsonbackReference效果很好。

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

有时可能会导入其他软件包,并且无法解决问题。

另外添加

import com.fasterxml.jackson.annotation.JsonIdentityInfo;
@JsonIdentityInfo(
        generator = ObjectIdGenerators.PropertyGenerator.class,
        property = "id")

模型的类定义效果很好。

您也可以使用如下态公共类用户{}

最新更新