【问题标题】:JPA many-to-many relationship causing infinite recursion and stack overflow errorJPA多对多关系导致无限递归和堆栈溢出错误
【发布时间】:2017-09-14 20:01:48
【问题描述】:

我正在开发一个 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)
...

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

【问题讨论】:

  • @JacksonIgnore for your collection 应该可以解决您的问题
  • 确实如此(假设您的意思是@JsonIgnore)。你是救生员!
  • 你能反序列化而不丢失信息吗?
  • 我不需要通过 JSON 发送有关关注者的信息,因此丢失这些信息对我来说不是问题。

标签: java postgresql jpa eclipselink


【解决方案1】:

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

【讨论】:

  • 对于多对多关系@JsonIdentityInfo 工作正常。
【解决方案2】:

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

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

@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 响应中将不再有任何循环。所以我认为最好的解决方案也是为关系表创建一个存储库并从那里访问数据。

希望对某人有所帮助!

【讨论】:

    【解决方案3】:

    我认为以前的答案中的问题是注释的包。在文章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")
    

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

    【讨论】:

      【解决方案4】:
      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;
      }
      

      【讨论】:

      • 您的答案可以通过额外的支持信息得到改进。请edit 添加更多详细信息,例如引用或文档,以便其他人可以确认您的答案是正确的。你可以找到更多关于如何写好答案的信息in the help center
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2017-09-05
      • 2020-07-25
      • 2018-06-19
      • 2011-02-26
      相关资源
      最近更新 更多