You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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:使用序列化引用注解配对

分别在父级、子级关联字段上添加配对注解,明确序列化规则:

  1. 在Branch类的inventory字段上添加@JsonManagedReference,标识为父级引用,正常序列化:
@OneToMany(mappedBy = "branch", cascade = CascadeType.ALL, orphanRemoval = true)
@JsonManagedReference // 新增这行
private Set<Inventory> inventory = new HashSet<>();
  1. 在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.24 17:24:01