Spring Boot自关联多对多关系引发StackOverflowError问题解决
StackOverflowError 解决:Spring Boot 自关联用户关注关系
我是Spring Boot和Java新手,最近在做用户关注功能时,用自关联的tb_user表实现双向关注关系,结果触发了StackOverflowError。一开始试了@JsonIgnore和@JsonIdentityInfo注解,都没解决问题,最后通过调整JPA关系映射和业务代码逻辑搞定了,分享一下过程:
原实体类代码
@Entity @Table(name = "tb_user") public class User { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; private String username; // 关注的用户 @ManyToMany @JoinTable( name = "tb_user_follow", joinColumns = @JoinColumn(name = "follower_id"), inverseJoinColumns = @JoinColumn(name = "following_id") ) private List<User> following; // 粉丝 @ManyToMany(mappedBy = "following") private List<User> followers; // IDE自动生成的getter、setter、toString方法 }
报错栈信息
java.lang.StackOverflowError at com.example.demo.entity.User.toString(User.java:45) at java.base/java.lang.String.valueOf(String.java:3367) at java.base/java.lang.StringBuilder.append(StringBuilder.java:168) at java.base/java.util.AbstractCollection.toString(AbstractCollection.java:473) at com.example.demo.entity.User.toString(User.java:45) // 重复递归调用栈省略...
问题根源
- toString循环引用:IDE自动生成的
toString()会递归打印following和followers集合,导致无限循环调用,直接触发栈溢出。 - JSON序列化循环:之前加
@JsonIgnore时位置不对,且没处理业务代码中的双向关联遍历;@JsonIdentityInfo未生效是因为没指定正确的生成器配置。
解决步骤
1. 修正实体类映射与注解
调整注解位置,重写toString方法避免递归:
@Entity @Table(name = "tb_user") // 配置JSON序列化时用ID标识对象,避免循环 @JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "id") public class User { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; private String username; // 关注列表:序列化时忽略,避免反向递归 @ManyToMany @JoinTable( name = "tb_user_follow", joinColumns = @JoinColumn(name = "follower_id"), inverseJoinColumns = @JoinColumn(name = "following_id") ) @JsonIgnore private List<User> following; // 粉丝列表:序列化时只返回ID,而非完整对象 @ManyToMany(mappedBy = "following") @JsonSerialize(contentUsing = ToStringSerializer.class) private List<User> followers; // 重写toString,只打印基础字段,不包含关联集合 @Override public String toString() { return "User{" + "id=" + id + ", username='" + username + '\'' + '}'; } // 自定义getter、setter方法 }
2. 优化业务查询逻辑
避免一次性加载双向关联集合,按需查询:
@Service public class UserService { @Autowired private UserRepository userRepository; // 查询用户基础信息+粉丝列表(仅加载粉丝基础数据) public User getUserWithFollowers(Long userId) { return userRepository.findById(userId) .orElseThrow(() -> new RuntimeException("用户不存在")); } // 单独提供关注列表查询接口,按需加载 public List<User> getFollowingList(Long userId) { User user = userRepository.findById(userId).orElseThrow(); return user.getFollowing(); } }
3. 验证结果
调整后,toString方法不再递归调用,JSON序列化时也不会触发循环引用,StackOverflowError问题彻底解决。
内容的提问来源于stack exchange,提问作者cornstar94
相关产品推荐
相关产品推荐

