导出到json时生成的数据库实体的循环依赖性

时间:2017-07-19 11:49:21

标签: java mysql json jpa

我有一个看起来像这样的数据库

db

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}

我希望这是有道理的。

知道怎么解决这个问题吗?

1 个答案:

答案 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序列化程序之前控制关联并删除任何循环。