Spring 6.1.12迁移至Hibernate 6.5.2时PersistenceProvider兼容异常
将Spring 6.1.12应用迁移至Hibernate 6.5.2.Final(搭配jakarta.persistence-api 3.1.0)时,应用启动抛出错误:创建名为entityManagerFactory的Bean失败,提示org.springframework.orm.jpa.vendor.SpringHibernateJpaPersistenceProvider未实现要求的jakarta.persistence.spi.PersistenceProvider接口。
当前Spring配置
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"> <property name="dataSource" ref="dataSource" /> <property name="jpaVendorAdapter"> <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter" /> </property> <property name="jpaProperties"> <props> <prop key="hibernate.dialect">${hibernate.dialect}</prop> <prop key="hibernate.hbm2ddl.auto">update</prop> <prop key="hibernate.show_sql">true</prop> <prop key="hibernate.format_sql">true</prop> </props> </property> </bean> <bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager"> <property name="entityManagerFactory" ref="entityManagerFactory" /> </bean>
环境信息
- Spring ORM: 6.1.12
- Hibernate: 6.5.2.Final
- Persistence API: 3.1.0(Jakarta EE)
错误详情
在Jakarta EE 9+环境中,SpringHibernateJpaPersistenceProvider未实现jakarta.persistence.spi.PersistenceProvider接口。
已尝试操作
- 确认所有依赖使用jakarta.*包
- 检查Hibernate与Spring版本兼容性,但问题仍存在
疑问
- 如何正确配置Spring ORM以搭配Hibernate 6.x和jakarta.persistence APIs?
- 是否有其他方式配置LocalContainerEntityManagerFactoryBean?
- Hibernate 6.x搭配Jakarta EE 9+时,正确的persistenceProvider类是什么?
核心问题原因
Spring 6.x已完全切换到Jakarta EE规范,SpringHibernateJpaPersistenceProvider在Spring 6.x中本应实现jakarta.persistence.spi.PersistenceProvider,出现未实现错误的核心原因是依赖冲突:项目中混入了旧版javax.persistence相关依赖,或者Spring ORM与Hibernate的版本适配出现类加载冲突。
1. 正确配置Spring ORM + Hibernate 6.x + Jakarta Persistence
方式一:修正现有XML配置,显式指定Hibernate的Jakarta版Provider
直接在LocalContainerEntityManagerFactoryBean中指定Hibernate官方的Jakarta Persistence实现类,覆盖默认的Spring实现:
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"> <property name="dataSource" ref="dataSource" /> <!-- 显式指定Hibernate的Jakarta版PersistenceProvider --> <property name="persistenceProviderClass" value="org.hibernate.jpa.HibernatePersistenceProvider" /> <property name="jpaVendorAdapter"> <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter" /> </property> <property name="jpaProperties"> <props> <prop key="hibernate.dialect">${hibernate.dialect}</prop> <prop key="hibernate.hbm2ddl.auto">update</prop> <prop key="hibernate.show_sql">true</prop> <prop key="hibernate.format_sql">true</prop> </props> </property> </bean>
方式二:简化配置,移除JpaVendorAdapter
如果不需要HibernateJpaVendorAdapter的自动适配逻辑,可以直接通过核心属性配置:
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"> <property name="dataSource" ref="dataSource" /> <property name="persistenceProviderClass" value="org.hibernate.jpa.HibernatePersistenceProvider" /> <!-- 可选:指定实体类扫描路径,替代persistence.xml --> <property name="packagesToScan" value="com.yourproject.entity" /> <property name="jpaProperties"> <props> <prop key="hibernate.dialect">${hibernate.dialect}</prop> <prop key="hibernate.hbm2ddl.auto">update</prop> <prop key="hibernate.show_sql">true</prop> <prop key="hibernate.format_sql">true</prop> </props> </property> </bean>
2. 解决依赖冲突
执行以下步骤排查并清理依赖:
- 使用Maven的
mvn dependency:tree或Gradle的./gradlew dependencies命令,检查是否存在javax.persistence:javax.persistence-api、旧版Hibernate(5.x及以下)等依赖,这些会导致类加载冲突。 - 确保所有JPA相关依赖均为Jakarta版本:
- 替换
javax.persistence-api为jakarta.persistence:jakarta.persistence-api:3.1.0 - 确保Hibernate依赖为
org.hibernate:hibernate-core:6.5.2.Final(该版本默认依赖Jakarta Persistence) - Spring ORM 6.1.12本身已依赖Jakarta Persistence,无需额外引入旧版javax依赖。
- 替换
3. 疑问逐一解答
- 正确配置方式:确保依赖无冲突,显式指定Hibernate的Jakarta版
PersistenceProvider,同时使用Spring 6.x提供的Jakarta兼容类(如HibernateJpaVendorAdapter在Spring 6.x中已适配Jakarta规范)。 - 其他配置方式:可以使用JavaConfig替代XML配置,示例如下:
@Configuration @EnableTransactionManagement public class JpaConfig { @Autowired private DataSource dataSource; @Bean public LocalContainerEntityManagerFactoryBean entityManagerFactory() { LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean(); em.setDataSource(dataSource); em.setPersistenceProviderClass(HibernatePersistenceProvider.class); em.setPackagesToScan("com.yourproject.entity"); Properties jpaProps = new Properties(); jpaProps.setProperty("hibernate.dialect", "org.hibernate.dialect.MySQLDialect"); jpaProps.setProperty("hibernate.hbm2ddl.auto", "update"); jpaProps.setProperty("hibernate.show_sql", "true"); jpaProps.setProperty("hibernate.format_sql", "true"); em.setJpaProperties(jpaProps); return em; } @Bean public JpaTransactionManager transactionManager(EntityManagerFactory emf) { JpaTransactionManager transactionManager = new JpaTransactionManager(); transactionManager.setEntityManagerFactory(emf); return transactionManager; } }
- 正确的PersistenceProvider类:Hibernate 6.x搭配Jakarta EE 9+时,使用
org.hibernate.jpa.HibernatePersistenceProvider,这是Hibernate官方提供的Jakarta Persistence规范实现类。
内容的提问来源于stack exchange,提问作者Pulkit Soni

