我有一个看起来像这样的数据库
除了recipe
之外的所有表格都有一个
recipe_id int not null, foreign key (recipe_id) references recipes(id)
我使用 eclipse 中的 JPA 工具自动生成了我的实体,但不是外键 recipe_id
我得到了类似的东西
//bi-directional many-to-one association to Recipe
@ManyToOne
private Recipe recipe;
例如,当我尝试将我所有的食谱导出为 json 格式时,我得到了一个 stackoverflow 异常,那是因为当它写入 json 时,它获取了过敏原,我的过敏原类有一个 Recipe 对象(指向含有某些过敏原的食谱),因此它会再次写入该 Recipe 对象,依此类推。
此外,当我尝试简单地打印一个食谱时,我得到以下输出,考虑到当我从 mysql 添加数据时我的所有外键都已正确设置
allergens={IndirectList: not instantiated}, ingredients={IndirectList: not instantiated}, mediaitems={IndirectList: not instantiated}, nutritionvalues={IndirectList: not instantiated}, steps={IndirectList: not instantiated}
我希望这是有道理的。
知道如何解决这个问题吗?
最佳答案
导出到 json 试图将您的 java bean 序列化为文本形式。在 Java 中,双向关联非常常见且有用,例如您的食谱和媒体项之间的关联。两个对象都相互引用。然而,这种循环关联不能用 json 或实际上任何文本形式表示,因为它们本质上是扁平的树状结构。
大多数 json 编码器的工作方式是检查应该被序列化的对象实例,并遍历其所有可访问的属性。对于每个属性,编码器将再次以递归方式调用该函数。因此,如果您有循环关联,递归将永远持续下去,直到 jvm 耗尽堆栈内存 - 因此会出现 stwckOverflowException。
由于这是一个常见问题,因此有多种解决方案可用。一些 json 库支持循环检测,当他们发现与堆栈中已有对象的循环关联时,他们不会尝试再次编码它——而是忽略它或只打印它的 ID。看看Jackson's backreference例如。
另一种策略是将数据模型与 json 模型分开,通常称为 DTO 映射。在这种情况下,您创建了一组类似于您的实体的新 pojo 类,并具有某种将实体映射到 dto 的 beanmapper,反之亦然。这样您就可以在将数据提交到 json 序列化程序之前控制关联并删除任何循环。
关于java - 导出到 json 时生成的数据库实体的循环依赖,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45189669/