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

Spring Boot JSON序列化无限递归:@JsonIgnoreProperties为何失效?

问题根源分析

你遇到的无限递归栈溢出错误,核心是双向多对多关联的序列化循环引用,加上额外定义了UserCourse中间表实体,导致JPA关联关系与Jackson序列化逻辑冲突,进而让@JsonIgnoreProperties未按预期生效。

1. 矛盾的多对多关联配置(核心问题)

你同时使用@ManyToMany注解和独立的UserCourse中间表实体,这是冲突的:

  • @ManyToMany适用于中间表仅包含两个外键(无额外字段/主键)的场景,JPA会自动维护该表;
  • 但你给中间表添加了user_course_id主键并定义为实体,这种情况下应该用一对多+多对一替代多对多关联,而非继续使用@ManyToMany。

这种冲突会导致JPA加载关联数据时逻辑混乱,Jackson序列化时的循环引用无法被@JsonIgnoreProperties正确拦截。

2. @JsonIgnoreProperties的生效局限性

当前注解参数逻辑本身没问题,但如果关联数据是懒加载状态,Jackson序列化时会触发Hibernate懒加载代理对象的初始化,此时@JsonIgnoreProperties可能无法作用于代理对象的属性,导致循环引用无法被阻断。


解决步骤

方案一:修正关联关系(推荐)

既然存在独立的UserCourse中间表实体,放弃@ManyToMany,改用@OneToMany和@ManyToOne:

修改User类

public class User implements UserDetails {
    // 其他字段保持不变...

    // 替换原有@ManyToMany注解
    @OneToMany(mappedBy = "user", cascade = CascadeType.ALL, orphanRemoval = true)
    @JsonIgnoreProperties("user") // 忽略UserCourse中的user属性,避免循环
    private List<UserCourse> userCourses;
}

修改Course类

public class Course {
    // 其他字段保持不变...

    // 替换原有@ManyToMany注解
    @OneToMany(mappedBy = "course", cascade = CascadeType.ALL, orphanRemoval = true)
    @JsonIgnoreProperties("course") // 忽略UserCourse中的course属性
    private List<UserCourse> userCourses;
}

UserCourse类保持不变

public class UserCourse {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "user_course_id")
    private Long userCourseId;

    @ManyToOne
    @JoinColumn(name = "user_id")
    private User user;

    @ManyToOne
    @JoinColumn(name = "course_id")
    private Course course;
}

方案二:保留@ManyToMany并移除UserCourse实体

如果中间表不需要额外字段(仅包含user_id和course_id),可删除UserCourse实体,同时调整序列化注解确保生效:

修正User类

@ManyToMany
@JoinTable(
        name = "user_course",
        joinColumns = @JoinColumn(name = "user_id"),
        inverseJoinColumns = @JoinColumn(name = "course_id")
)
@JsonIgnoreProperties("users") // 忽略Course中的users集合
private List<Course> courses;

修正Course类

@ManyToMany(mappedBy = "courses")
@JsonIgnore // 直接忽略users集合,避免循环引用
private List<User> users;

改用@JsonIgnore更直接,可规避@JsonIgnoreProperties可能的生效问题。

方案三:解决懒加载导致的序列化问题

如果坚持现有@ManyToMany配置,需确保Jackson不会触发懒加载代理初始化:

  • 在application.properties添加配置:spring.jackson.serialization.fail-on-empty-beans=false;
  • 或用@JsonIgnore替代@JsonIgnoreProperties标记关联字段;
  • 也可使用@JsonBackReference和@JsonManagedReference标记双向关联:
    // User类中
    @ManyToMany
    @JoinTable(...)
    @JsonManagedReference // 标记主动端,正常序列化
    private List<Course> courses;
    
    // Course类中
    @ManyToMany(mappedBy = "courses")
    @JsonBackReference // 标记被动端,序列化时自动忽略
    private List<User> users;
    

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.27 08:53:10