【问题标题】:Infinite Recursion with JSON and Hibernate JPAJSON 和 Hibernate JPA 的无限递归
【发布时间】:2018-10-02 07:21:26
【问题描述】:

使用spring Boot,尝试将JPA对象转换为JSON时,我不断收到此错误:

nested exception is 
  `org.springframework.http.converter.HttpMessageNotWritableException:
     Could not write JSON: Infinite recursion (StackOverflowError); 
    nested exception is com.fasterxml.jackson.databind.
JsonMappingException: Infinite recursion (StackOverflowError)
 (through reference chain: interv.Entities.AppUser["projects"]->org.hibernate.collection.internal.PersistentBag[0]->interv.Entities.Project["appUser"]->interv.Entities.AppUser["projects"]->org.hibernate.collection.internal.Persis`

按照堆栈溢出的一些解决方案,我通过添加注释来结束 @JsonIgnoreProperties,所以我的实体项目看起来像这样:

@Entity
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Project implements Serializable{

        @Id @GeneratedValue
        private long id;
        private String intitule;
        private String description;

        @OneToMany(mappedBy = "project" , fetch = FetchType.EAGER)
       @Fetch(value = FetchMode.SUBSELECT)
        @JsonIgnoreProperties("contrats")
        private Collection<Contrat> contrats;

        @ManyToOne
        @JoinColumn(name = "Id_appUser")
        @JsonIgnoreProperties("appUser")
        private AppUser appUser;
 }

restful 的 API 是这样的:

    import java.util.List;

@RestController
public class ProjectsController {

    @Autowired
    private ProjectRepo projectRepo;

    @RequestMapping(path = "/ListProjects", method = RequestMethod.GET)
    public List<Project> getProjects(){
        return projectRepo.findAll();
    }

我尝试了其他注释,但我一直收到同样的错误:

在 ARC 扩展中我得到:

200 正常

解析 JSON 数据时出错

JSON 输入意外结束

提前感谢您的帮助:)。

编辑:

文件 AppUser.java

@Entity
@Data
@AllArgsConstructor @NoArgsConstructor
public class AppUser implements Serializable {

    @Id @GeneratedValue
    private Long id;
    @Column(unique = true)
    private String username;
    private String password;
    @ManyToMany(fetch = FetchType.EAGER)
    private Collection<AppRole> roles = new ArrayList<>();

    @OneToMany(mappedBy = "appUser" , fetch = FetchType.EAGER)
    @Fetch(value = FetchMode.SUBSELECT)
    private Collection<Project> projects = new ArrayList<>();


    @OneToMany(mappedBy = "appUser" , fetch = FetchType.EAGER)
    @Fetch(value = FetchMode.SUBSELECT)
    private Collection<Intervention> interventions = new ArrayList<>();

    @OneToMany(mappedBy = "appUser" , fetch = FetchType.EAGER)
    @Fetch(value = FetchMode.SUBSELECT)
    private Collection<Contrat> contrats = new ArrayList<>();

}

【问题讨论】:

  • 根据错误消息,由于 appUser 属性,链无限继续。尝试在类级别添加 @JsonIgnoreProperties,包括合同和 appUser 属性。
  • @K.SivaPrasadReddy 首先感谢您的帮助,正如我在帖子中提到的那样,我已将注释 JsonIgnoreProperties 添加到属性 appUser 中,但我一直收到相同的错误,是您告诉的方式吗我该怎么办?
  • @在类级别添加它是什么意思?
  • @dEs12ZER AppUser 包含一个项目列表???
  • @SEY_91 是的,实体 AppUser 包含一个项目集合

标签: java json hibernate spring-boot input


【解决方案1】:

出现问题是因为生成 JSON 时存在无限循环。您可以使用@JsonManagedReference 和@JsonBackReference 来解决无限递归。

@Entity
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Project implements Serializable{

        @Id @GeneratedValue
        private long id;
        private String intitule;
        private String description;

        @OneToMany(mappedBy = "project" , fetch = FetchType.EAGER)
       @Fetch(value = FetchMode.SUBSELECT)
        @JsonIgnoreProperties("contrats")
        private Collection<Contrat> contrats;

        @ManyToOne
        @JoinColumn(name = "Id_appUser")
        @JsonBackReference
        private AppUser appUser;
 }

应用用户

@Entity
@Data
@AllArgsConstructor @NoArgsConstructor
public class AppUser implements Serializable {

    @Id @GeneratedValue
    private Long id;
    @Column(unique = true)
    private String username;
    private String password;
    @ManyToMany(fetch = FetchType.EAGER)
    private Collection<AppRole> roles = new ArrayList<>();

    @OneToMany(mappedBy = "appUser" , fetch = FetchType.EAGER)
    @Fetch(value = FetchMode.SUBSELECT)
    @JsonManagedReference
    private Collection<Project> projects = new ArrayList<>();


    @OneToMany(mappedBy = "appUser" , fetch = FetchType.EAGER)
    @Fetch(value = FetchMode.SUBSELECT)
    private Collection<Intervention> interventions = new ArrayList<>();

    @OneToMany(mappedBy = "appUser" , fetch = FetchType.EAGER)
    @Fetch(value = FetchMode.SUBSELECT)
    private Collection<Contrat> contrats = new ArrayList<>();

}

【讨论】:

  • 我完全按照你的建议做了,但我得到了这个错误:java.lang.IllegalArgumentException: Can not handle managed/back reference 'defaultReference': back reference type (java.util.Collection) not compatible托管类型(interv.Entities.Project)
  • 使用List而不是collection时同样的错误
  • 对不起,@JsonManagedReference 必须应用于集合,现在看看它是否有效。
  • 你拯救了我的一天!非常感谢它现在可以工作了!
猜你喜欢
  • 2011-03-20
  • 1970-01-01
  • 2020-06-25
  • 2015-11-28
相关资源
最近更新 更多