SpringBoot2.7.2升3.2.0+Java8转17时@DependsOnDatabaseInitialization循环依赖问题
Spring Boot 3.2.0 + Java 17 迁移问题解决
一、循环依赖问题(webSecurityConfig → ... → jpaSharedEM_entityManagerFactory ↔ dataSourceScriptDatabaseInitializer)
原因
Spring Boot 3.x 对数据库初始化组件(dataSourceScriptDatabaseInitializer)和JPA容器的依赖关系做了调整。当给依赖JPA Repository的bean(比如systemInitialService)添加@DependsOnDatabaseInitialization时,会强制该bean等待数据库脚本执行完成,但Repository代理的创建又依赖jpaSharedEM_entityManagerFactory,而EntityManagerFactory的初始化又依赖就绪的数据源,最终形成闭环依赖链。
正确解决方案(替代直接删除注解)
直接删除@DependsOnDatabaseInitialization会导致初始化逻辑提前执行(JPA容器未就绪),不是最优解。换用以下方式保证初始化时机:
- 把
systemInitialService里的初始化逻辑(比如默认用户创建)抽出来,放到CommandLineRunner或ApplicationListener<ContextRefreshedEvent>中:@Component public class SystemInitializer implements CommandLineRunner { private final UserRepository1 userRepository; public SystemInitializer(UserRepository1 userRepository) { this.userRepository = userRepository; } @Override public void run(String... args) throws Exception { // 原来的初始化逻辑,比如创建默认用户 if (userRepository.findByUsername("admin").isEmpty()) { // 创建并保存默认用户逻辑 } } } - 移除
systemInitialService上的@DependsOnDatabaseInitialization注解,让Spring自动管理bean依赖,初始化逻辑会在整个应用上下文就绪后执行,既避开循环依赖,又保证数据库和JPA容器都已就绪。
二、无法解析jpaSharedEM_entityManagerFactory / SpringHibernateJpaPersistenceProvider未实现Jakarta接口问题
原因
Spring Boot 3.x 完全基于Jakarta EE规范(取代旧Java EE/Javax),要求Hibernate版本必须是6.0+(只有Hibernate 6.x才实现了jakarta.persistence.spi.PersistenceProvider接口)。触发该错误的常见场景:
- 手动引入了Hibernate 5.x及以下版本的依赖
- 第三方依赖间接引入了旧版Hibernate
- 代码中残留
javax.persistence相关引用
解决方案
- 依赖对齐:用Spring Boot Starter管理Hibernate版本
删掉所有手动指定的hibernate-core、hibernate-entitymanager等依赖,直接使用spring-boot-starter-data-jpa,它会自动引入与Spring Boot 3.2.0兼容的Hibernate版本(6.4.x系列):<!-- pom.xml 中只保留这个,不要手动加Hibernate依赖 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-jpa</artifactId> </dependency> - 排查依赖冲突
用构建工具命令检查依赖树,找出引入旧版Hibernate的来源:- Maven:
mvn dependency:tree | grep hibernate - Gradle:
./gradlew dependencies | grep hibernate
找到后通过exclusions排除旧版依赖,比如:
<dependency> <groupId>com.example</groupId> <artifactId>old-third-party-lib</artifactId> <exclusions> <exclusion> <groupId>org.hibernate</groupId> <artifactId>hibernate-core</artifactId> </exclusion> </exclusions> </dependency> - Maven:
- 全局替换JPA引用为Jakarta
把代码中所有javax.persistence.*的导入替换为jakarta.persistence.*,包括实体类、Repository接口、自定义注解等,避免残留的javax引用导致兼容性问题。
内容的提问来源于stack exchange,提问作者Subodh Joshi
相关产品推荐
相关产品推荐

