Spring Boot升级后创建entityManagerFactory时Java堆内存溢出
问题背景
原应用基于Spring Boot 2.6.4 + javax.persistence,为适配spring-data-jpa-datatables:6.0.1升级至Spring Boot 3.1.2,替换为jakarta.persistence,注释掉实体类的@Audited注解后,启动耗时极长并抛出OutOfMemoryError: Java heap space,堆栈指向Hibernate在处理实体关联时的循环调用逻辑。
解决方案
1. 修复实体类双向关联配置
Hibernate 6对关联映射的初始化逻辑更严格,双向关联未正确配置会导致元模型初始化时无限递归遍历:
- 确保所有双向一对多/多对一关联正确设置
mappedBy,避免重复映射关系 - 将默认的
FetchType.EAGER改为FetchType.LAZY,减少启动时加载的关联数据量
示例代码:
// 多对一关联端 @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "parent_id") private ParentEntity parent; // 一对多关联端 @OneToMany(mappedBy = "parent", fetch = FetchType.LAZY) private List<ChildEntity> children = new ArrayList<>();
2. 临时增大JVM堆内存
在应用启动参数中调整堆内存参数,临时缓解溢出问题:
-Xmx4G -Xms2G
注:此为临时方案,需结合代码优化解决根本问题
3. 限制Hibernate关联抓取深度
在application.properties中添加配置,限制Hibernate初始化时的关联抓取深度:
spring.jpa.properties.hibernate.max_fetch_depth=1
避免因深层关联导致的递归内存消耗。
4. 排查依赖兼容性冲突
检查spring-data-jpa-datatables:6.0.1与Spring Boot 3.1.2的依赖兼容性,执行命令查看依赖树:
mvn dependency:tree
若存在Hibernate版本冲突,强制指定与Spring Boot 3.1.2匹配的Hibernate版本(Spring Boot 3.1.2默认适配Hibernate 6.2.x)。
5. 正确恢复审计功能(可选)
若需要保留审计功能,不要直接注释@Audited,替换为Jakarta版本的Spring Data Envers依赖:
<dependency> <groupId>org.springframework.data</groupId> <artifactId>spring-data-envers</artifactId> <version>3.1.2</version> </dependency>
同时确保实体类使用org.springframework.data.jpa.domain.support.AuditingEntityListener,并在启动类添加@EnableJpaAuditing注解。
内容的提问来源于stack exchange,提问作者Jaiylon

