Spring Boot Cloud JPA出现StackOverflowError无堆栈信息求助
排查Spring Boot Cloud中JPA
Handler dispatch failed: java.lang.StackOverflowError 问题 针对你遇到的无堆栈信息的StackOverflowError问题,结合代码场景,可按以下步骤排查:
1. 强制输出完整堆栈跟踪
StackOverflowError有时会被JVM截断堆栈,需添加JVM启动参数强制打印完整调用链:
-XX:+PrintStackTrace -XX:MaxJavaStackTraceDepth=1000
完整堆栈能直接定位递归调用的源头,是最关键的排查步骤。
2. 检查实体类toString方法的递归风险
你在forceSave中调用了model.toString(),若Drzava的toString方法包含gradovi集合,而Grad实体的toString又引用了Drzava,会直接触发递归调用:
- 若使用Lombok的
@ToString,需明确排除关联集合:@ToString(exclude = "gradovi") public class Drzava extends BaseEntity<Long> { // ... 其他属性 } - 若自定义toString方法,确保不包含关联的集合属性。
3. 验证BaseMapper/BaseEntity的循环映射逻辑
你使用了自定义的BaseMapper和BaseEntity,需排查:
- MapStruct的
BaseMapper是否默认映射所有实体属性?即使DrzavaDTO中没有gradovi,若父类Mapper未排除该属性,可能尝试递归映射Grad与Drzava的关联,需在DrzavaMapper中明确忽略:@Mapper(componentModel = "spring") public interface DrzavaMapper extends BaseMapper<Drzava, DrzavaDTO, Long> { @Mapping(target = "gradovi", ignore = true) Drzava toModel(DrzavaDTO dto); } - 检查
BaseEntity的equals/hashCode方法是否包含关联属性,这类方法在JPA持久化过程中可能被频繁调用,触发递归。
4. 排查Hibernate代理对象的懒加载递归
Hibernate的懒加载代理对象在触发属性访问时(如toString、序列化),可能加载关联的Grad实体,而Grad又引用Drzava形成循环:
- 确认
@OneToMany注解的fetch类型为LAZY(默认值,可显式声明):@OneToMany(mappedBy = "drzava", fetch = FetchType.LAZY) private Set<Grad> gradovi; - 避免在事务内调用关联集合的toString、size等方法,防止触发懒加载。
5. 检查事务代理的递归调用
forceSave方法标注了@Transactional,Spring会生成代理对象:
- 排查
BaseService中是否存在方法互相调用导致的代理循环,比如save方法内部触发了其他带事务的方法,而该方法又回调save; - 检查实体类的
@PrePersist/@PreUpdate回调方法,是否存在递归调用逻辑。
6. 验证依赖版本兼容性
由于你已提交Spring JPA Bug,可尝试降级依赖验证是否为版本问题:
- 降级Spring Boot Cloud到3.1.0;
- 降级MySQL Connector/J到8.0.32;
- 观察问题是否消失,缩小版本兼容问题范围。
7. 简化测试用例定位问题
- 编写单元测试直接调用
service.forceSave,跳过Web层,若问题复现则说明根源在服务层; - 若仅通过控制器POST请求触发,需检查请求体的反序列化逻辑,比如请求JSON是否存在嵌套结构导致Jackson反序列化递归。
内容的提问来源于stack exchange,提问作者Glisa060
相关产品推荐
相关产品推荐

