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

JPA双向一对多映射添加@Json注解仍触发toString无限循环求助

JPA双向一对多映射toString无限循环栈溢出问题解决

问题背景

使用JPA对接Oracle数据库,为scheme_code_templates与multilingual_template_v2表实现双向一对多、多对一映射。已添加@JsonManagedReference和@JsonBackReference注解解决JSON序列化循环问题,但调用SchemeCodeRepository的findAll()并输出multilingualTemplates时,出现toString无限循环的栈溢出错误。

相关代码与信息

MultilingualTemplateV2 实体类

@Entity
@Table(name = "multilingual_template_v2")
@Data
@AllArgsConstructor
@NoArgsConstructor
@Builder
@ToString
public class MultilingualTemplateV2 {

    @NotNull()
    String language;

    @NotNull()
    @Nationalized
    String template;

    @Id
    @Column(name="template_code")
    @NotNull()
    String templateCode;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "associated_schemecode")
    @JsonManagedReference
    SchemeCode schemeCode;
}

SchemeCode 实体类

@Entity
@Table(name = "scheme_code_templates")
@Data
@AllArgsConstructor
@NoArgsConstructor
@Builder
@ToString
public class SchemeCode {

    @Column(name="associated_pushcode")
    Integer associatedPushcode;

    @NotNull
    String description;

    @Id
    @NotNull()
    String schemeCode;

    @OneToMany(mappedBy = "schemeCode", cascade = CascadeType.ALL, fetch = FetchType.EAGER)
    @JsonBackReference
    List<MultilingualTemplateV2> multilingualTemplates;
}

报错栈信息

at org.hibernate.collection.spi.PersistentBag.toString(PersistentBag.java:585) ~[hibernate-core-6.1.7.Final.jar:6.1.7.Final]
    at java.lang.String.valueOf(String.java:4218) ~[?:?]
    at java.lang.StringBuilder.append(StringBuilder.java:173) ~[?:?]
    at com.dcb.smsbatch.dataLayer.entities.SchemeCode.toString(SchemeCode.java:34) ~[classes/:?]
    at java.lang.String.valueOf(String.java:4218) ~[?:?]
    at java.lang.StringBuilder.append(StringBuilder.java:173) ~[?:?]
    at com.dcb.smsbatch.dataLayer.entities.MultilingualTemplateV2.toString(MultilingualTemplateV2.java:30) ~[classes/:?]
    ...(循环重复的栈信息)

问题原因

Lombok的@ToString注解默认生成包含所有字段的toString方法,包括关联的实体对象。当SchemeCode的toString方法包含multilingualTemplates列表时,列表中的每个MultilingualTemplateV2对象调用toString又会引用SchemeCode对象,形成无限循环调用,最终导致栈溢出。

注意:@JsonManagedReference和@JsonBackReference仅解决JSON序列化时的循环问题,对toString方法的循环引用无效。

解决方案

通过Lombok的注解排除toString中的关联字段,打破循环引用:

方案1:在@ToString注解中指定排除字段

修改两个实体类的@ToString注解,排除引发循环的关联字段:

修改后的MultilingualTemplateV2

@Entity
@Table(name = "multilingual_template_v2")
@Data
@AllArgsConstructor
@NoArgsConstructor
@Builder
@ToString(exclude = "schemeCode") // 排除关联的SchemeCode对象
public class MultilingualTemplateV2 {
    // 字段与注解不变
}

修改后的SchemeCode

@Entity
@Table(name = "scheme_code_templates")
@Data
@AllArgsConstructor
@NoArgsConstructor
@Builder
@ToString(exclude = "multilingualTemplates") // 排除关联的列表
public class SchemeCode {
    // 字段与注解不变
}

方案2:使用@ToString.Exclude标记单个字段

在关联字段上直接添加@ToString.Exclude注解,更精准地排除:

MultilingualTemplateV2 修改示例

@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "associated_schemecode")
@JsonManagedReference
@ToString.Exclude // 排除该字段在toString中
SchemeCode schemeCode;

SchemeCode 修改示例

@OneToMany(mappedBy = "schemeCode", cascade = CascadeType.ALL, fetch = FetchType.EAGER)
@JsonBackReference
@ToString.Exclude // 排除该字段在toString中
List<MultilingualTemplateV2> multilingualTemplates;

验证测试

修改实体类后重新运行测试代码:

for (SchemeCode schemeCode : schemeRepo.findAll()) {
    System.out.println(schemeCode.getMultilingualTemplates());
}

此时输出multilingualTemplates时,toString方法不会再触发循环调用,避免栈溢出问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.21 07:40:00