JPA Hibernate多对多关联出现Jackson无限递归栈溢出错误如何解决
问题根因
你遇到的报错核心原因是Jackson序列化时的循环引用导致无限递归:Branch实体中定义了Set<Inventory> inventory属性关联当前分馆的所有库存记录,而Inventory实体中又定义了Branch branch属性关联所属分馆。接口返回数据序列化JSON的过程中,Jackson会反复遍历Branch->inventory->branch->inventory的引用链,最终触发栈溢出。
日志里的ErrorMvcAutoConfiguration$StaticView是Spring Boot未找到自定义错误页时的附属提示,不是问题根源。
可行解决方案
方案1:直接忽略循环字段(快速解决)
在Inventory类的branch属性上添加@JsonIgnore注解,序列化时会跳过该字段,直接打断循环链:
@ManyToOne(fetch = FetchType.LAZY) @MapsId("branch_id") @JsonIgnore // 新增这行 private Branch branch;
如果不需要在序列化库存时返回所属分馆信息,这个方案最简单。
方案2:使用序列化引用注解配对
分别在父级、子级关联字段上添加配对注解,明确序列化规则:
- 在
Branch类的inventory字段上添加@JsonManagedReference,标识为父级引用,正常序列化:
@OneToMany(mappedBy = "branch", cascade = CascadeType.ALL, orphanRemoval = true) @JsonManagedReference // 新增这行 private Set<Inventory> inventory = new HashSet<>();
- 在
Inventory类的branch字段上添加@JsonBackReference,标识为子级引用,序列化时跳过:
@ManyToOne(fetch = FetchType.LAZY) @MapsId("branch_id") @JsonBackReference // 新增这行 private Branch branch;
方案3:使用DTO传输层(工程规范推荐)
不要直接将JPA实体类作为接口返回值,单独定义数据传输对象(DTO),仅保留前端需要的字段,从根源避免循环引用:
- 定义
InventoryDTO,仅存放bookId、qty等需要返回的字段,不关联Branch对象 - 定义
BranchDTO,存放id、name、address和List<InventoryDTO>集合 - 接口查询到实体后,手动或借助工具类转换为DTO再返回
这个方案同时还能避免暴露实体的敏感字段,更符合工程分层规范。
方案4:标记对象唯一标识避免重复序列化
在两个实体类上添加@JsonIdentityInfo注解,Jackson序列化时遇到已经出现过的对象,只会输出其id值,不会重复序列化整个对象:
// 在Branch类上加 @JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "id") @Entity(name="Branch") @Table(name="tblLibraryBranch") public class Branch { ... } // 在Inventory类上加 @JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "id") @Entity(name="Inventory") @Table(name = "tblBookCopies") public class Inventory { ... }
内容的提问来源于stack exchange,提问作者Mint
相关产品推荐
相关产品推荐

