升级Spring Boot 2.7.2后EntityManagerFactoryBuilder注入失败求助
问题背景
将spring-boot-starter-parent从2.6.9版本升级至2.7.2版本,spring-boot-autoconfigure随父依赖同步升级后,自定义EntityManagerFactory的配置类出现依赖注入失败问题。
配置类代码
自定义的EntityManagerFactory配置方法:
@Primary @Bean(name = "localEntityManagerFactory") public LocalContainerEntityManagerFactoryBean entityManagerFactory(EntityManagerFactoryBuilder builder) { return builder .dataSource(localDataSource()) .packages("entity.local") .build(); }
错误提示
- IntelliJ IDEA编译提示:
Could not autowire. No beans of 'EntityManagerFactoryBuilder' type found.
- 应用运行时错误:
Parameter 0 of method entityManagerFactory in ***.config.db.LocalDataSourceConfig required a bean of type 'org.springframework.boot.orm.jpa.EntityManagerFactoryBuilder' that could not be found.
Action:
Consider defining a bean of type 'org.springframework.boot.orm.jpa.EntityManagerFactoryBuilder' in your configuration.
现有pom.xml配置
<parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.6.9</version> <relativePath/> </parent> <dependencies> <!-- spring-boot-starter --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <!-- database --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-jpa</artifactId> </dependency> <dependency> <groupId>com.vladmihalcea</groupId> <artifactId>hibernate-types-52</artifactId> <version>${hibernate.types.52.version}</version> </dependency> <dependency> <groupId>org.liquibase</groupId> <artifactId>liquibase-core</artifactId> </dependency> <dependency> <groupId>org.postgresql</groupId> <artifactId>postgresql</artifactId> <scope>runtime</scope> </dependency> <dependency> <groupId>com.microsoft.sqlserver</groupId> <artifactId>mssql-jdbc</artifactId> <scope>runtime</scope> </dependency> </dependencies>
解决方法
Spring Boot 2.7版本调整了JPA自动配置逻辑:当完全自定义LocalContainerEntityManagerFactoryBean时,不再自动注册EntityManagerFactoryBuilder Bean,需要手动构建或注册该Bean。
方法一:手动构建EntityManagerFactoryBuilder
注入JpaProperties和HibernateProperties,手动创建EntityManagerFactoryBuilder并合并Hibernate属性:
@Primary @Bean(name = "localEntityManagerFactory") public LocalContainerEntityManagerFactoryBean entityManagerFactory(JpaProperties jpaProperties, HibernateProperties hibernateProperties) { // 创建JPA厂商适配器(默认使用Hibernate) JpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter(); // 构建EntityManagerFactoryBuilder EntityManagerFactoryBuilder builder = new EntityManagerFactoryBuilder(vendorAdapter, jpaProperties.getProperties(), null); // 合并JPA与Hibernate配置属性 Map<String, Object> hibernateProps = hibernateProperties.determineHibernateProperties( jpaProperties.getProperties(), new HibernateSettings() ); return builder .dataSource(localDataSource()) .packages("entity.local") .properties(hibernateProps) .build(); }
方法二:注册EntityManagerFactoryBuilder为Bean
在配置类中添加EntityManagerFactoryBuilder的Bean定义,后续直接注入使用:
@Bean public EntityManagerFactoryBuilder entityManagerFactoryBuilder(JpaProperties jpaProperties, ObjectProvider<JpaVendorAdapter> jpaVendorAdapters) { // 优先使用容器中的JpaVendorAdapter,无则创建默认的Hibernate适配器 JpaVendorAdapter vendorAdapter = jpaVendorAdapters.getIfAvailable(HibernateJpaVendorAdapter::new); return new EntityManagerFactoryBuilder(vendorAdapter, jpaProperties.getProperties(), null); } // 原有的entityManagerFactory方法保持不变 @Primary @Bean(name = "localEntityManagerFactory") public LocalContainerEntityManagerFactoryBean entityManagerFactory(EntityManagerFactoryBuilder builder) { return builder .dataSource(localDataSource()) .packages("entity.local") .build(); }
内容的提问来源于stack exchange,提问作者polyackov_ot

