JPA使用@ManyToMany注解关联实体时出现JSON序列化无限递归错误
问题描述
我创建了两个映射数据库表的实体类,二者通过标注了@ManyToMany注解的变量建立关联。但我尝试向项目中添加学生时,出现了无限递归错误。
我曾参考多个相关教程和技术社区方案尝试解决,均未生效。
Student类代码如下:
@Entity @Table(name = "student") @Data @NoArgsConstructor @AllArgsConstructor public class Student { @Id @GeneratedValue @Column(name="student_id") private Integer studentId; @Column(nullable = false, length = 50) private String imie; @Column(nullable = false, length = 100) private String nazwisko; @Column(unique=true, nullable = false, length = 50, name = "nr_indeksu") private String nrIndeksu; @Column(nullable = false, length = 50) private String email; @Column(nullable = false) private boolean stacjonarny; @ManyToMany(mappedBy = "studenci") @JsonIgnore private Set<Projekt> projekty; @Column(nullable = false, length = 50) private String haslo; }
Projekt类代码如下:
@Entity @Table(name = "projekt") @Data @NoArgsConstructor @AllArgsConstructor public class Projekt { @Id @GeneratedValue @Column(name = "projekt_id") private Integer projektId; @Column(nullable = false, length = 50) private String nazwa; @Column(nullable = false, length = 1000) private String opis; @Column(nullable = false, name = "dataczas_utworzenia") private LocalDateTime dataczasUtworzenia; @Column(nullable = false, name = "data_oddania") private LocalDate dataOddania; @OneToMany(mappedBy = "projekt") @JsonIgnoreProperties(value ={"projekt"}, allowSetters = true) private List<Zadanie> zadania; @ManyToMany @JoinTable(name = "projekt_student", joinColumns = {@JoinColumn(name="projekt_id")}, inverseJoinColumns = {@JoinColumn(name="student_id")}) private Set<Student> studenci; }
报错日志如下:
2021-08-04 17:26:15.991 WARN 18144 --- [nio-8080-exec-3] .w.s.m.s.DefaultHandlerExceptionResolver : Resolved [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: org.springframework.data.domain.PageImpl["content"]->java.util.Collections$UnmodifiableRandomAccessList[7]->com.project.rest.model.Student["projekty"])] 2021-08-04 17:26:15.991 WARN 18144 --- [nio-8080-exec-3] o.h.e.loading.internal.LoadContexts : HHH000100: Fail-safe cleanup (collections) : org.hibernate.engine.loading.internal.CollectionLoadContext@f1ff33b<rs=HikariProxyResultSet@922089472 wrapping org.postgresql.jdbc.PgResultSet@57f69f62> 2021-08-04 17:26:15.991 WARN 18144 --- [nio-8080-exec-3] o.h.e.loading.internal.LoadContexts : HHH000100: Fail-safe cleanup (collections) : org.hibernate.engine.loading.internal.CollectionLoadContext@4110461d<rs=HikariProxyResultSet@1176750721 wrapping org.postgresql.jdbc.PgResultSet@57ac7e31> 2021-08-04 17:26:15.991 WARN 18144 --- [nio-8080-exec-3] o.h.e.loading.internal.LoadContexts : HHH000100: Fail-safe cleanup (collections) : org.hibernate.engine.loading.internal.CollectionLoadContext@275ad9d4<rs=HikariProxyResultSet@919944575 wrapping org.postgresql.jdbc.PgResultSet@44345fd2> 2021-08-04 17:26:15.991 WARN 18144 --- [nio-8080-exec-3] o.h.e.loading.internal.LoadContexts : HHH000100: Fail-safe cleanup (collections) : org.hibernate.engine.loading.internal.CollectionLoadContext@7d7d9e7<rs=HikariProxyResultSet@1405186173 wrapping org.postgresql.jdbc.PgResultSet@33be62da> 2021-08-04 17:26:15.991 WARN 18144 --- [nio-8080-exec-3] o.h.e.loading.internal.LoadContexts : HHH000100: Fail-safe cleanup (collections) : org.hibernate.engine.loading.internal.CollectionLoadContext@42db9900<rs=HikariProxyResultSet@1173506052 wrapping org.postgresql.jdbc.PgResultSet@24f79446> 2021-08-04 17:26:15.991 WARN 18144 --- [nio-8080-exec-3] o.h.e.loading.internal.LoadContexts : HHH000100: Fail-safe cleanup (collections) : org.hibernate.engine.loading.internal.CollectionLoadContext@1dd679de<rs=HikariProxyResultSet@844941445 wrapping org.postgresql.jdbc.PgResultSet@5d3e700c> 2021-08-04 17:26:15.991 WARN 18144 --- [nio-8080-exec-3] o.h.e.loading.internal.LoadContexts : HHH000100: Fail-safe cleanup (collections) : org.hibernate.engine.loading.internal.CollectionLoadContext@43b3e132<rs=HikariProxyResultSet@824582406 wrapping org.postgresql.jdbc.PgResultSet@5bfe18a6> 2021-08-04 17:26:15.991 WARN 18144 --- [nio-8080-exec-3] o.h.e.loading.internal.LoadContexts : HHH000100: Fail-safe cleanup (collections) : org.hibernate.engine.loading.internal.CollectionLoadContext@75c8828e<rs=HikariProxyResultSet@1405429510 wrapping org.postgresql.jdbc.PgResultSet@5b58222b> 2021-08-04 17:26:15.991 WARN 18144 --- [nio-8080-exec-3] o.h.e.loading.internal.LoadContexts : HHH000100: Fail-safe cleanup (collections) : org.hibernate.engine.loading.internal.CollectionLoadContext@73ee203<rs=HikariProxyResultSet@1788253192 wrapping org.postgresql.jdbc.PgResultSet@2caee16a>
解决方案
首先排查最常见的导包错误:你在Student类projekty字段上加的@JsonIgnore如果导入的是org.hibernate.annotations.JsonIgnore,不会对Jackson序列化生效,正确导入包应为com.fasterxml.jackson.annotation.JsonIgnore。
如果确认导包正确仍报错,或你需要在序列化时保留双向关联的字段信息,可使用@JsonIgnoreProperties注解避免循环,具体修改如下:
- 移除Student类
projekty字段上的@JsonIgnore,替换为@JsonIgnoreProperties("studenci"),表示序列化Projekt集合时忽略其内部的studenci字段 - 给Projekt类的
studenci字段加上@JsonIgnoreProperties("projekty"),表示序列化Student集合时忽略其内部的projekty字段
修改后的核心代码片段如下:
Student类关联字段修改
@ManyToMany(mappedBy = "studenci") @JsonIgnoreProperties("studenci") private Set<Projekt> projekty;
Projekt类关联字段修改
@ManyToMany @JoinTable(name = "projekt_student", joinColumns = {@JoinColumn(name="projekt_id")}, inverseJoinColumns = {@JoinColumn(name="student_id")}) @JsonIgnoreProperties("projekty") private Set<Student> studenci;
该方案既不会触发递归序列化,又能在返回Student时携带关联的Projekt列表、返回Projekt时携带关联的Student列表,兼顾业务需求和序列化要求。
内容的提问来源于stack exchange,提问作者PiotrKulesza
相关产品推荐
相关产品推荐

