Spring Data JPA @OneToOne 注释无限递归错误

Hol*_*inc 3 spring hibernate jpa

老公.java

package com.example.demo.com.example.domain;

import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import lombok.ToString;

import javax.persistence.*;


//@Data
//@NoArgsConstructor
//@EqualsAndHashCode
//@ToString
@Entity
@Table(name = "t_husban")
public class Husband {
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;

    private String name;
    private String job;

    @OneToOne
    @JoinColumn(name = "wife_fk",referencedColumnName = "id")
    private Wife wife;

    //omitted getter/setter
}
Run Code Online (Sandbox Code Playgroud)

老婆.java

package com.example.demo.com.example.domain;

import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import lombok.ToString;

import javax.persistence.*;

//@Data
//@NoArgsConstructor
@EqualsAndHashCode(exclude = "husband",callSuper = false)
@Entity
@Table(name = "t_wife")
public class Wife {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;

    private String name;

    @OneToOne(mappedBy = "wife",cascade = {CascadeType.ALL})
    private Husband husband;

    //omitted getter/setter
}
Run Code Online (Sandbox Code Playgroud)

服务.java

@Service

    public class TestOneToOneEitherSide {

        @Autowired
        private WifeRepository wifeDao;

        @Autowired
        private HusbandRepository husbandDao;
        public Husband testCreate() {

            Husband husband = husbandDao.findByName("Wang");
            return husband;
        }
    }
Run Code Online (Sandbox Code Playgroud)

当我使用 spring 数据 jpa 从数据库中查询丈夫时,结果中发生了无限递归,见下图。使用 @OneToOne 注释时出了什么问题?有人能给我一些建议吗?或者我以错误的方式使用注释。

图片

Ame*_*bsa 6

这是一个已知问题,当您有双向关系时,jackson 会尝试将一侧的每个引用从另一侧序列化,因此具有无限递归是合乎逻辑的。

解决方案:有很多解决方案,您可以在一侧使用@JsonIgnore 以避免序列化带注释的引用从而破坏无限递归

 @EqualsAndHashCode(exclude = "husband",callSuper = false)
 @Entity
@Table(name = "t_wife")
public class Wife {

@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;

private String name;

@OneToOne(mappedBy = "wife",cascade = {CascadeType.ALL})
@JsonIgnore
private Husband husband;

//omitted getter/setter
}
Run Code Online (Sandbox Code Playgroud)

你也可以使用@JsonManagedReference/@JsonBackReference,检查这个链接了解更多信息如何使用它们

这个答案有一个问题,如果您尝试序列化妻子方向,您将没有丈夫对象,因为解决方案是避免序列化它。

对此有一个很好的解决方案,在此链接中提到,其想法是生成对父实体的引用,因此如果您正在序列化丈夫,您将拥有丈夫->妻子->[引用丈夫而不是丈夫] ,您需要做的就是使用 @JsonIdentityInfo 注释您的实体

@EqualsAndHashCode(exclude = "husband",callSuper = false)
@Entity
@Table(name = "t_wife")
@JsonIdentityInfo(generator=ObjectIdGenerators.UUIDGenerator.class, property="@id")
public class Wife {

@JsonIdentityInfo(generator=ObjectIdGenerators.UUIDGenerator.class, property="@id")
@Entity
@Table(name = "t_husban")
public class Husband {
@Id
Run Code Online (Sandbox Code Playgroud)