Spring Boot中Lombok+Hibernate实体报HashMap.hash栈溢出错误
错误根因
你遇到的StackOverflowError是双向关联实体类的循环hash调用导致的:
Goal和User是双向关联关系,你用Lombok默认生成的hashCode方法会自动包含所有类字段- 计算
Goal的哈希值时会调用关联User对象的hashCode,计算User的哈希值时又会遍历goalSet调用每个Goal的hashCode,最终形成无限递归,触发栈溢出 - 报错触发在
HashMap.hash方法是因为你把查询结果收集为HashSet时,会自动调用每个元素的hashCode方法,刚好触发递归逻辑
解决方案
1. 排除关联字段,避免Lombok生成循环逻辑
在两个实体的关联字段上添加@EqualsAndHashCode.Exclude和@ToString.Exclude注解,让Lombok生成hashCode、equals、toString方法时跳过这些关联字段:Goal实体修改:
@ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "user_id") @OnDelete(action = OnDeleteAction.CASCADE) @EqualsAndHashCode.Exclude @ToString.Exclude private User userss;
User实体修改:
// 按需加载改为LAZY,避免每次查询User都强制拉取所有关联Goal,提升性能 @OneToMany(mappedBy = "userss", fetch = FetchType.LAZY) @OnDelete(action = OnDeleteAction.CASCADE) @EqualsAndHashCode.Exclude @ToString.Exclude private Set<Goal> goalSet = new HashSet<>();
2. 优化查询方法写法
指定HQL查询的返回类型,避免无意义的强转和裸类型使用:
按用户ID查询目标集:
@Override public Set<Goal> findByUserId(Long userId){ return getSession().createQuery("from Goal where userss.id =:userId", Goal.class) .setParameter("userId", userId) .stream() .collect(Collectors.toSet()); }
查询所有目标:
@Override public Set<Goal> getGoals() { return getSession().createQuery("from Goal", Goal.class) .stream() .collect(Collectors.toSet()); }
3. 进阶优化(可选)
如果对外返回数据不需要返回完整实体,可以自定义DTO类接收查询结果,从根源上避免实体类的循环依赖问题暴露到外部调用。
内容的提问来源于stack exchange,提问作者nameless
相关产品推荐
相关产品推荐

