【问题标题】:Spring JPA Multiple Relations with same entitySpring JPA 具有相同实体的多个关系
【发布时间】:2016-05-02 04:58:01
【问题描述】:

我有以下关系:

我正在尝试在 Spring Boot 中使用 JPA 映射这些关系,但我遇到了一些麻烦。这些是类:

人物:

public class Person {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    private String name;

    // Relations

    @OneToOne
    @JoinColumn(name = "child_id")
    private PersonBirth birth;

    @OneToMany
    @JoinColumn(name = "mother_id")
    private List<PersonBirth> motherOf;

    @OneToMany
    @JoinColumn(name = "father_id")
    private List<PersonBirth> fatherOf;
}

人物出生:

public class Birth {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Column(name = "birth_date")
    @JsonProperty(value = "birth_date")
    private Long birthDate;

    // Relations

    @OneToOne
    @JoinColumn(name = "child_id")
    private Person child;

    @ManyToOne
    @JoinColumn(name = "mother_id")
    private Person mother;

    @ManyToOne
    @JoinColumn(name = "father_id")
    private Person father;
}

我正在尝试获取Pearson 和他的Birth 数据,包括他的motherfather。并且还可以得到一个Person,其子代由fatherOfmotherOf 映射。但是现在的方式是,当我获取一个母亲的Person 时,它会抛出stackoverflow,因为它获取了包含child 数据的Birth 数据(到目前为止我想要的),其中包含他的Birth 数据,包含他的母亲,包含她的孩子(等等)。我不知道我正在尝试做的事情是否可以使用这种结构,或者我是否必须改变它......任何建议都表示赞赏。

【问题讨论】:

  • @JsonIgnore 与 JPA 没有任何关系。因此,请更详细地说明您的问题。一般来说,这种关系在 JPA 中是没有问题的。
  • @dunni 编辑了问题,看看是否更清楚。谢谢。
  • 您应该将您提出的原始问题反过来,这与杰克逊图书馆有关,您需要在其中一个注释@JsonManagedReference,在许多参考文献上注释@JsonBackReference

标签: java spring jpa spring-boot spring-data


【解决方案1】:

根据您的描述,我猜在将结构序列化为 JSON 时会出现问题。如果你使用 Jackson(这是 Spring Boot 的默认设置),你可以使用 @JsonManagedReference@JsonBackReference 注解:

public class Person {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    private String name;

    // Relations

    @OneToOne
    @JoinColumn(name = "child_id")
    @JsonManagedReference("birth")
    private PersonBirth birth;

    @OneToMany
    @JoinColumn(name = "mother_id")
    @JsonManagedReference("mother")
    private List<PersonBirth> motherOf;

    @OneToMany
    @JoinColumn(name = "father_id")
    @JsonManagedReference("father")
    private List<PersonBirth> fatherOf;
}

public class Birth {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Column(name = "birth_date")
    @JsonProperty(value = "birth_date")
    private Long birthDate;

    // Relations

    @OneToOne
    @JoinColumn(name = "child_id")
    @JsonBackReference("birth")
    private Person child;

    @ManyToOne
    @JoinColumn(name = "mother_id")
    @JsonBackReference("mother")
    private Person mother;

    @ManyToOne
    @JoinColumn(name = "father_id")
    @JsonBackReference("father")
    private Person father;
}

这样,Jackson 不会序列化整个对象以供反向引用,而只是序列化标识符。

文档:http://wiki.fasterxml.com/JacksonFeatureBiDirReferences

【讨论】:

  • 是的,这样我就摆脱了循环,但我无法获得我想要的数据。就像,如果我得到Person 和他的Birth 数据,我无法看到motherfather 数据只有idbirthDateBirth
【解决方案2】:

只是添加@dunni 回答的内容:

为了让Jackson能够很好地工作,关系的两侧之一不应该被序列化,以避免烦人的无限递归循环导致stackoverflow错误。

Jackson 将引用的前向部分,例如 java 类的属性(即 User 类中的 List 角色),并将其转换为类似 json 的存储格式;这就是所谓的编组过程。 然后,Jackson 查找引用的后面部分(即,在 Role 类中列出用户)并保持原样,而不是对其进行序列化。这部分关系将在前向引用的反序列化(解组)期间重新构建。

参考: http://keenformatics.blogspot.com/2013/08/how-to-solve-json-infinite-recursion.html

【讨论】:

  • 因此,考虑到这一点以及我创建的结构,我将无法使用他的子数据获得Person(无需使用单独的查询操作和填充字段,例如一个查询获取 Person 数据和另一个查询以获取他的孩子)?
猜你喜欢
  • 2011-03-24
  • 2015-07-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-04-07
  • 2019-12-31
  • 2020-10-26
相关资源
最近更新 更多