Spring JPA与同一实体的多重关系

时间:2016-01-25 18:54:31

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

我有以下关系:

Relation database

我试图在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;
}

PersonBirth:

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。并且也可以通过PersonfatherOf生成motherOf其子项。但是它现在的方式,当我获取一个母亲Person时,它会抛出stackoverflow,因为它获取Birth数据,其中包含child数据(到目前为止我是想要),包含他的Birth数据,包含他的母亲,包含她的孩子(等等)。我不知道我尝试做什么是可能使用这种结构,或者我是否必须改变它......任何建议都值得赞赏。

2 个答案:

答案 0 :(得分:0)

从您的描述中,我猜想在将结构序列化为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;
}

这样,杰克逊不会将整个对象序列化为后向引用,而只是标识符。

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

答案 1 :(得分:0)

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

为了让Jackson运行良好,关系的两个方面之一不应该被序列化,以避免恼人的无限递归循环导致stackoverflow错误。

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

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