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

Spring Boot中mappedBy参数为何引发无限递归?

解决JPA双向关联+Jackson序列化引发的StackOverflow错误

问题场景

现有Business和ProductCategory两个JPA实体类,二者是一对多双向关联关系,遇到以下矛盾问题:

  • 只使用@JsonManagedReference和@JsonBackReference但不配置mappedBy时,JSON序列化不会触发无限递归,但没法正确建立双向关联;
  • 加上mappedBy配置正确的双向关联后,反而出现StackOverflowError。

问题代码示例

@Entity
@Getter
@Setter
@ToString
@NoArgsConstructor
@AllArgsConstructor
public class Business {

    @OneToMany(targetEntity = ProductCategory.class
            , cascade = CascadeType.ALL
            , fetch = FetchType.LAZY
            , mappedBy = "business"
    )
    @JsonManagedReference
    private List<ProductCategory> productCategories;
}

@Entity
@Getter
@Setter
@ToString
@NoArgsConstructor
@AllArgsConstructor
public class ProductCategory {

    @ManyToOne(targetEntity = Business.class
            , cascade = CascadeType.ALL
            , fetch = FetchType.LAZY)
    @JoinColumn(name = "business_id")
    @JsonBackReference
    private Business business;
}

问题根源

罪魁祸首是Lombok的@ToString注解!当JPA通过mappedBy建立起正确的双向关联后,Lombok自动生成的toString方法会递归调用关联对象的toString——比如Business.toString()会调用每个ProductCategory.toString(),而每个ProductCategory.toString()又会调用Business.toString(),无限循环直接导致栈溢出。Jackson的注解已经处理了JSON序列化的递归问题,和它无关。

修复方案

方案1:自定义toString方法,排除关联字段

给两个实体类的@ToString注解添加exclude参数,排除掉关联字段,避免递归调用:

修改后的Business类:

@Entity
@Getter
@Setter
@ToString(exclude = "productCategories")
@NoArgsConstructor
@AllArgsConstructor
public class Business {

    @OneToMany(targetEntity = ProductCategory.class
            , cascade = CascadeType.ALL
            , fetch = FetchType.LAZY
            , mappedBy = "business"
    )
    @JsonManagedReference
    private List<ProductCategory> productCategories;
}

修改后的ProductCategory类:

@Entity
@Getter
@Setter
@ToString(exclude = "business")
@NoArgsConstructor
@AllArgsConstructor
public class ProductCategory {

    @ManyToOne(targetEntity = Business.class
            , cascade = CascadeType.ALL
            , fetch = FetchType.LAZY)
    @JoinColumn(name = "business_id")
    @JsonBackReference
    private Business business;
}

方案2:直接移除@ToString注解

如果不需要自动生成的toString方法,直接删掉两个实体类上的@ToString注解,也能解决问题。

验证

修改后,既可以通过mappedBy保持正确的JPA双向关联,Jackson的注解也能正常处理JSON序列化的递归问题,不会再出现StackOverflowError。

内容的提问来源于stack exchange,提问作者Nikola

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.06 10:45:19