我有一个看起来像这样的数据库
除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}
我希望这是有道理的。
知道怎么解决这个问题吗?
答案 0 :(得分:0)
导出到json正在尝试将您的java bean序列化为文本形式。在java中,拥有像你的食谱和mediaitem之间的双向关联是非常普遍和有用的。两个对象都相互引用。然而,这种循环关联不能用json或实际上任何文本形式表示,因为它们本身就是扁平的树状结构。
大多数json marshallers工作的方式是,他们检查应该序列化的对象实例,并迭代其所有可访问的属性。对于每个属性,marshaller将以递归方式再次调用该函数。因此,如果你有循环关联,递归将一直持续到jvm用完堆栈内存 - 因此stwckOverflowException。
由于这是一个常见问题,因此可以使用多种解决方案。一些json libs支持循环检测,当它们发现与已经在其堆栈中的对象的循环关联时,它们将不会再次尝试对其进行编组 - 而是将其忽略或仅打印它的Id。例如,请查看Jackson's backreference。
另一种策略是将数据模型与json模型分开,通常称为DTO映射。在这种情况下,您创建一组与您的实体类似的新pojo类,并使用某种beanmapper将实体映射到dtos,反之亦然。这样,您可以在将数据提交到json序列化程序之前控制关联并删除任何循环。