【问题标题】:Spring-data-mongodb @DBRef causing infinite recursion? I can't work out whySpring-data-mongodb @DBRef 导致无限递归?我不知道为什么
【发布时间】:2017-05-18 04:47:53
【问题描述】:

好的,所以我的 Spring 应用程序中有一组非常简单的 Java POJO。

这是我的person类:

@Document(collection="people")
public class Person {    

    // Data.
    @Id
    private ObjectId Id;    

    @DBRef
    private List<Entity> entities;    


    /* Getters and setters removed to keep this question simple. */
}    

还有,这是我的实体类。

@Document(collection = "entities")
public class Entity {    

    @Id
    private ObjectId Id;    

    @DBRef
    private List<Person> people;    

    /* Getters and setters removed to keep question simple. */
}    

现在,在我的规范中,“Person”和“Entity”具有多对多关系。一个人可以注册到很多实体,反之亦然。

现在,由于某种原因,当我尝试将这两个持久化到彼此的列表中时,我得到了这个我从未见过的奇怪错误:

2017-05-17 23:37:51.966 ERROR 29918 --- [nio-8080-exec-1] 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 content: Infinite recursion (StackOverflowError) (through reference chain: restServer.dto.Entity["people"]->java.util.ArrayList[0]->restServer.dto.Person["entity"]->restServer.dto.Entity["people"]->java.util.ArrayList[0]->restServer.dto.Person["entity"]->restServer.dto.Entity["people"]->java.util.ArrayList[0]->restServer.dto.Person["entity"]->restServer.dto.Entity["people"]->java.util.ArrayList[0]->restServer.dto.Person["entity"]->restServer.dto.Entity["people"]->java.util.ArrayList[0]->restServer.dto.Person["entity"]->restServer.dto.Entity["people"]->java.util.ArrayList[0]->restServer.dto.Person["entity"]->restServer.dto.Entity["people"]->java.util.ArrayList[0]->restServer.dto.Person["entity"]->restServer.dto.Entity["people"]->java.util.ArrayList[0]->restServer.dto.Person["entity"]->restServer.dto.Entity["people"]->java.util.ArrayList[0]->restServer.dto.Person["entity"]->restServer.dto.Entity["people"]->java.util.ArrayList[0]->restServer.dto.Person["entity"]->restServer.dto.Entity["people"]->java.util.ArrayList[0]->restServer.dto.Person["entity"]->restServer.dto.Entity["people"]->java.util.ArrayList[0]->restServer.dto.Person["entity"]->restServer.dto.Entity["people"]->java.util.ArrayList[0]->restServer.dto.Person["entity"]->restServer.dto.Entity["people"]->java.util.ArrayList[0]->restServer.dto.Person["entity"]->restServer.dto.Entity["people"]->java.util.ArrayList[0]->restServer.dto.Person["entity"]->restServer.dto.Entity["people"]->java.util.ArrayList[0]->restServer.dto.Person["entity"]->restServer.dto.Entity["people"]->java.util.ArrayList[0]->restServer.dto.Person["entity"]->restServer.dto.Entity["people"]->java.util.ArrayList[0]->restServer.dto.Person["entity"]->restServer.dto.Entity["people"]->java.util.ArrayList[0]->restServer.dto.Person["entity"]->restServer.dto.Entity["people"]->java.util.ArrayList[0]->restServer.dto.Person["entity"]->restServer.dto.Entity["people"]->java.util.ArrayList[0]->restServer.dto.Person["entity"]->restServer.dto.Entity["people"]->java.util.ArrayList[0]->restServer.dto.Person["entity"]->restServer.dto.Entity["people"] 

... This continues until the stack overflows. Sorry it is all on one line, wasn't sure how to fix that on this site... it is cut straight from my terminal. 

我做错了什么?到目前为止,我在学习这个堆栈方面做得很好,但我看不出这里有什么问题。

【问题讨论】:

  • 是的,这种情况肯定会发生。您可以通过注释您的 List 人员来处理它; & 列出 实体;使用 @DBRef(lazy = true) 而不是 @DBRef
  • 太棒了,谢谢,实际的区别是什么?
  • 检查我的答案

标签: java spring mongodb spring-data spring-data-mongodb


【解决方案1】:

是的,这种情况可能会发生! 假设你有:

person1 = {"entities" : ["entity1", "entity2"]}
entity1 = {"persons" : ["person1", "person2"]}

因此,使用上述配置,当 spring 尝试加载“person1”时,它也会加载其相关的“entities(entity1 & entity2)”。现在当spring尝试加载“entity1”时,它又要加载“person1”等等,这肯定会导致循环依赖/递归!

restServer.dto.Person["entity"]->restServer.dto.Entity["people"]->java.util.ArrayList[0]->restServer.dto.Person["entity"]->restServer.dto.Entity["people"]...

所以你可以通过多种方式处理这个问题:

1。将您的列表注释为惰性:

@Document(collection="people")
public class Person {    

    // Data.
    @Id
    private ObjectId Id;    

    @DBRef(lazy = true)
    private List<Entity> entities;    


    /* Getters and setters removed to keep this question simple. */
} 

@Document(collection = "entities")
public class Entity {    

    @Id
    private ObjectId Id;    

    @DBRef(lazy = true)
    private List<Person> people;    

    /* Getters and setters removed to keep question simple. */
}

lazy = true 将阻止 Spring 加载不必要的实体,除非你需要它(你可以通过显式调用来加载它)

2。将列表实体作为嵌入式文档:

@Document(collection="people")
public class Person {    

    // Data.
    @Id
    private ObjectId Id;    
    private List<Entity> entities;    


    /* Getters and setters removed to keep this question simple. */
} 

@Document(collection = "entities")
public class Entity {    

    @Id
    private ObjectId Id;    
    private List<Person> people;    

    /* Getters and setters removed to keep question simple. */
}

但这完全取决于您的要求。

【讨论】:

  • 我明白了 - 如果我只希望这些链接管理人和实体之间的关系,哪个更好?
  • @IWishIWasABarista 使用“1。将您的列表注释为惰性:”,在第二个选项中,有很多重复并且没有数据完整性
  • 等等,如果我使用惰性,我会失去数据完整性吗?
  • 不幸的是,MongoDb/或其他 No-SQL 数据库中的数据完整性非常有限(与 RDBMS 相比)。而这种有限的数据完整性只有在你使用引用(使用@DBRef)时才能实现,无论它是 LAZY 还是 EAGER。如果您使用嵌入式文档,正如我在第二点中讨论的那样,那么就没有数据完整性!
  • 我实际上可能会在这里拥有自己的惰性机制,我只存储 ID 字符串,并在需要时解析它们。我实际上从来不需要立即获取相关项目的完整树。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-07-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多