【问题标题】:how to Fix spring boot one to many bidirectional infinity loop?如何修复弹簧靴一对多双向无限循环?
【发布时间】:2018-03-06 11:51:09
【问题描述】:

我正在尝试使用 spring boot 和 spring data jpa 创建一个一对多的双向映射,请查看下面的实体

雇主实体

@Entity  
public class Employer  
{  
private Long id;  
private String employerName;  
private List<Employee> employees;  

@Id  
@GeneratedValue(strategy=GenerationType.AUTO)  
public Long getId()  
{  
    return id;  
}  
public void setId(Long id)  
{  
    this.id = id;  
}  
public String getEmployerName()  
{  
    return employerName;  
}  
public void setEmployerName(String employerName)  
{  
    this.employerName = employerName;  
}  

@OneToMany(cascade=CascadeType.ALL, mappedBy="employer")  
public List<Employee> getEmployees()  
{  
    return employees;  
}  
public void setEmployees(List<Employee> employees)  
{  
    this.employees = employees;  
}  
} 

员工实体

@Entity  
public class Employee  
{  
private Long id;  
private String employeeName;  
private Employer employer;  

@Id  
@GeneratedValue(strategy=GenerationType.AUTO)  
public Long getId()  
{  
    return id;  
}  
public void setId(Long id)  
{  
    this.id = id;  
}  
public String getEmployeeName()  
{  
    return employeeName;  
}  
public void setEmployeeName(String employeeName)  
{  
    this.employeeName = employeeName;  
}  
@ManyToOne(cascade=CascadeType.ALL, fetch = FetchType.LAZY)  
public Employer getEmployer()  
{  
    return employer;  
}  
public void setEmployer(Employer employer)  
{  
    this.employer = employer;  
}  
}  

雇主回购

public interface EmployerServices extends JpaRepository<Employer, Long> {
}

员工回购

public interface EmployeeServices extends JpaRepository<Employee, Long> {
}

REST 控制器是

 @RestController
 public class Controller {
 @Autowired EmployeeServices employeeServices;
 @Autowired EmployerServices employerServices;
 @GetMapping("/getempr")
 public Object getempr(){
    return employerServices.findOne(1L);
 }
}

现在问题开始了,看看我的输出

它看起来像一个内讧循环,我的服务器抛出错误 getOutputStream() 已经被调用了这个响应。

 I used @JsonBackReference & @JsonManagedReference 

注释,但问题是它像一对多一样工作

 {
   "id":1,
   "employerName":"employer",
   "employees":[
     {"id":1,"employeeName":"emp1"},
     {"id":2,"employeeName":"emp2"}
   ]
}  

如果我想引起多对一的关注,就像所有员工与雇主一样。输出是

 [
  {
   "id":1,
   "employeeName":"emp1"
  },
  {
    "id":2,
    "employeeName":"emp2"}
 ]

它没有向我显示雇主详细信息。

请向我建议我做错了什么。提前谢谢!!

【问题讨论】:

    标签: spring spring-boot spring-data hibernate-mapping bidirectional


    【解决方案1】:

    不要使用@JsonBackReference@JsonManagedReference尝试使用注解@JsonIgnoreProperties

    @JsonIgnoreProperties("employer")
    private List<Employee> employees;  
    
    @JsonIgnoreProperties("employees")
    private Employer employer;  
    

    它阻止 Jackson 渲染关联对象的指定属性。

    【讨论】:

    • 感谢您的回答!!但是在按照您的建议添加注释后,如果获取员工详细信息,我会遇到异常
    • org.springframework.http.converter.HttpMessageNotWritableException:无法写入 JSON:找不到类的序列化程序
    • 谢谢,我得到了与惰性获取有关的问题!您能否解释一下(@JsonBackReferenceand,@JsonManagedReference)有什么问题以及如何用(@JsonIgnoreProperties)修复它。请多解释一下
    • 谢谢老兄,你节省了我的时间
    【解决方案2】:

    JSON 是双向映射的问题。使用以下属性。

    @JsonIgnoreProperties("employer")
    @JsonIgnoreProperties("employees")
    

    请继续以 Eager 的方式获取类型。

    希望这会奏效。

    【讨论】:

    • 上述建议适用于您**不希望 ** 员工详细信息出现在 **employer ** json 响应中。要显示员工详细信息,请不要在雇主实体中使用以下行(第一行以上)@JsonIgnoreProperties("employer")
    • 终于找到了我一直在寻找的答案 :) 谢谢!
    【解决方案3】:

    您可以通过使用注释进行两次修改来解决您的问题。
    Employer.class

    @Entity
    public class Employer {
        private Long id;
        private String employerName;
    
        @OneToMany(cascade = CascadeType.ALL,
                mappedBy = "employer",
                orphanRemoval = true)
        private List<Employee> employees;
    
        @Id
        @GeneratedValue(strategy = GenerationType.AUTO)
        public Long getId() {
            return id;
        }
    
        public void setId(Long id) {
            this.id = id;
        }
    
        public String getEmployerName() {
            return employerName;
        }
    
        public void setEmployerName(String employerName) {
            this.employerName = employerName;
        }
    
        public List<Employee> getEmployees() {
            return employees;
        }
    
        public void setEmployees(List<Employee> employees) {
            this.employees = employees;
        }
    }
    


    Employee.class

    @Entity
    public class Employee {
        private Long id;
        private String employeeName;
    
    
        @ManyToOne(fetch = FetchType.LAZY)
        @JoinColumn(name = "employer_id")
        private Employer employer;
    
        @Id
        @GeneratedValue(strategy = GenerationType.AUTO)
        public Long getId() {
            return id;
        }
    
        public void setId(Long id) {
            this.id = id;
        }
    
        public String getEmployeeName() {
            return employeeName;
        }
    
        public void setEmployeeName(String employeeName) {
            this.employeeName = employeeName;
        }
    
        public Employer getEmployer() {
            return employer;
        }
    
        public void setEmployer(Employer employer) {
            this.employer = employer;
        }
    }
    

    欲了解更多信息,请访问link

    【讨论】:

      【解决方案4】:

      像这样改变你的 getEmployer 方法:

      @ManyToOne(cascade=CascadeType.ALL, fetch = FetchType.LAZY)
      @JsonProperty(access = JsonProperty.Access.WRITE_ONLY)
      public Employer getEmployer()  
      {  
          return employer;  
      }
      

      【讨论】:

        【解决方案5】:

        使用

        @JsonProperty(access = Access.WRITE_ONLY)
        private List<Employee> employees;
        

        这样它会在响应中打印到 JSON 时忽略员工(从而防止循环),但仍会考虑您在请求正文中传递的 JSON 数据(员工列表),以便它可用于持久性。

        【讨论】:

          猜你喜欢
          • 2018-07-22
          • 2017-12-22
          • 1970-01-01
          • 2015-09-02
          • 2018-02-14
          • 2020-10-28
          • 2018-02-16
          • 2019-05-03
          • 1970-01-01
          相关资源
          最近更新 更多