具有相同实体的Spring JPA多个关系

qhhrdooz  于 2022-11-14  发布在  Spring
关注(0)|答案(3)|浏览(149)

我有以下关系:

我尝试在Sping Boot 中使用JPAMap这些关系,但是遇到了一些麻烦。

联系人:

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,它的孩子被fatherOf或者motherOfMap.但是现在的情况是,当我得到一个Person,它是一个母亲,因为它获取包含child数据的Birth数据(到目前为止我想要的),那包含他的Birth数据,那包含他的母亲,里面有她的孩子(等等)。我不知道我尝试做的事情是否可以使用这种结构,或者我是否必须改变它...任何建议都是感激的。

lztngnrs

lztngnrs1#

从您的描述中,我猜问题发生在将结构序列化为JSON时。如果您使用Jackson(Sping 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

vjrehmav

vjrehmav2#

只是为了补充什么@邓尼回答说:
为了让Jackson能很好地工作,关系的双方中的一方不应该被序列化,以避免恼人的无限递归循环导致stackoverflow错误。
Jackson取引用的forward部分,例如一个java类的属性(即List roles in User类),并将其转换为一个json类的存储格式;这就是所谓的编组过程。然后,Jackson查找引用的后面部分(即,在Role类中列出用户),并保持原样,而不对其进行序列化。关系的这一部分将在前向引用的反序列化(解编组)过程中重新构造。
参考:http://keenformatics.blogspot.com/2013/08/how-to-solve-json-infinite-recursion.html

suzh9iv8

suzh9iv83#

简单说明一下:使用@JsonIgnore@JsonManagedReference@JsonBackReference打破JSON序列化中的无限循环很容易,但也有严重的缺点,因为这些注解在具体序列化什么时会失去很大的灵活性。
在问题中描述的场景中,例如,你不能序列化一个人及其子对象,而不序列化他们的子对象等等。这是一种全有或全无的情况。
这就是为什么不应该在控制器方法中返回实体对象,而应该返回所谓的data transfer objects (DTOs);使用这些方法将允许您非常具体地进行序列化,并根据具体情况进行序列化,因为您可以决定为每个控制器方法使用哪个DTO。
例如,可以序列化包含所有相关人员姓名的PersonBirth,而不序列化其父母和子女。

相关问题