如何处理与杰克逊休眠的双向一对一关系

时间:2015-12-30 15:41:45

标签: java json hibernate jackson

我正在使用@JsonIgnore Annotation来防止在为响应创建Json时出现无限循环,并且它可以正常工作,但是我想知道是否有一些替代属性不是实际上被忽略但也阻止了无限循环。

例如,我的 entityA 具有以下属性:

int id
String name
EntityB example;

entityB

int id
String something
EntityA entityAExample //(this one goes with the JsonIgnore)

因此,如果我获得entityA中的所有寄存器,响应将如下所示:

[{
    "id":"1",
    "name": "name",
    "entityB": {
                 "id":"1",
                 "something": "text"
               }
}]

实体B看起来像:

[{
   "id":"1",
   "something": "text"
}]

它适用于我目前所需要的,但我希望实体B也可以包含entityA(或列表,如果是多对一关系),所以响应如下:

[{
    "id":"1",
    "something": "text",
    "entityAExample": {
                      "id":"1",
                      "name": "name"
                      }
}]

因此,无论我查询哪个实体,都会显示相关记录。

1 个答案:

答案 0 :(得分:2)

这是处理json时常见的双向关系问题。

我认为与杰克逊解决这个问题的最简单方法是使用@JsonIdentityInfo。您只需要使用以下内容注释您的类:

@Entity
@JsonIdentityInfo(generator=ObjectIdGenerators.PropertyGenerator.class, property="id")
public class EntityA{
    ...
}

@Entity
@JsonIdentityInfo(generator=ObjectIdGenerators.PropertyGenerator.class, property="id")
public class EntityB{
    ...
}

这样做的是,当之前已经被序列化的实体(父实体(EntityA))必须第二次序列化时才开始无限递归循环,它不会像往常一样被序列化。

相反,它将使用您在注释中指定的属性(id)进行序列化。

简而言之,注释允许您指定对象的替代表示形式,仅在实体启动无限循环时使用,从而打破该循环。

按照您的示例导致:

[{
    "id":"1",
    "name": "name",
    "entityB": {
                 "id":"2",
                 "something": "text"
                 "entityAExample": "1"                                       
               }
}]

您也可以只注释EntityB而不是两个实体,这将导致:

[{
    "id":"1",
    "name": "name",
    "entityB": {
                 "id":"2",
                 "something": "text"
                 "entityAExample": {
                                    "id": "1",
                                    "name": "name",
                                    "entityBExample": "2"                                         
                                   }
               }
}]

你也可以使用其他属性,而且通常可以正常工作。 Here's官方文档和wiki

Here's一篇文章更详细地解释了这个问题,而another则展示了解决这个问题的其他方法。