Spring Data JPA查询@OneToMany双向映射实体报StackOverflowError如何解决
问题根因
双向关联的JPA实体CustomerEntity和AccountEntity的toString方法形成了循环调用:
CustomerEntity的toString逻辑中直接打印关联字段accountEntities,会触发每个AccountEntity的toString调用AccountEntity的toString逻辑中又直接打印关联字段customerEntity,反过来触发CustomerEntity的toString调用
无限循环最终导致栈内存耗尽,抛出StackOverflowError。你业务代码中的System.out.println(customers)是触发toString调用的直接诱因。
解决方案
按优先级可选以下任意方案处理:
- 修改toString方法,打断循环调用
重写两个实体的toString方法时,排除双向关联字段,或者仅打印关联实体的主键字段而非完整对象,示例修改如下:// CustomerEntity的toString修改,移除accountEntities或仅打印账户编号 @Override public String toString() { return "CustomerEntity [id=" + id + ", firstName=" + firstName + ", lastName=" + lastName + ", dob=" + dob + ", mobileNumber=" + mobileNumber + ", emailId=" + emailId + ", address=" + address + ", createdTime=" + createdTime + "]"; } // AccountEntity的toString修改,移除customerEntity或仅打印关联客户id @Override public String toString() { return "AccountEntity [id=" + id + ", accountNumber=" + accountNumber + ", branch=" + branch + ", accountType=" + accountType + ", balance=" + balance + ", createdTime=" + createdTime + ", customerId=" + (customerEntity != null ? customerEntity.getId() : null) + "]"; } - 如果使用Lombok自动生成实体方法
在双向关联字段上添加@ToString.Exclude注解,避免Lombok自动生成的toString逻辑包含关联字段,同时建议同步给关联字段加@EqualsAndHashCode.Exclude,避免equals、hashCode方法也出现循环问题。 - 序列化/打印场景额外处理
若需要将实体序列化为JSON返回,可在关联字段上添加Jackson注解打断循环:在@OneToMany侧加@JsonManagedReference,@ManyToOne侧加@JsonBackReference,或者直接用@JsonIgnore忽略不需要序列化的关联字段。
补充注意事项
如果你需要在返回的CustomerDTO中包含关联账户信息,需要注意当前accountEntities的默认加载策略是懒加载,直接在事务外访问会抛出懒加载异常,建议自定义Repository查询方法,使用JOIN FETCH语句主动加载关联的accountEntities数据。
内容的提问来源于stack exchange,提问作者Sanal M
相关产品推荐
相关产品推荐

