Spring Boot3自定义JpaTransactionManager报错:EntityManagerFactory类型不匹配
一、SpringPhysicalNamingStrategy类找不到的问题
Spring Boot3 适配的是 Hibernate 6,Hibernate 6 对命名策略体系做了重构,原Spring Boot2中使用的org.springframework.boot.orm.jpa.hibernate.SpringPhysicalNamingStrategy已被移除,替代方案有两种:
1. 使用Hibernate 6原生命名策略
直接改用Hibernate官方提供的CamelCaseToUnderscoresNamingStrategy,它实现了和原SpringPhysicalNamingStrategy一致的驼峰转下划线功能,配置时替换类路径即可:
import org.hibernate.boot.model.naming.CamelCaseToUnderscoresNamingStrategy; // 在LocalContainerEntityManagerFactoryBean配置中替换 em.setPhysicalNamingStrategy(new CamelCaseToUnderscoresNamingStrategy());
2. 使用Spring Boot3提供的适配类
如果你更倾向于Spring提供的封装,Spring Boot3中保留了适配Hibernate6的命名策略类,需导入正确路径:
import org.springframework.boot.orm.jpa.hibernate.SpringPhysicalNamingStrategy;
若依然找不到,检查spring-boot-starter-data-jpa依赖版本是否为3.x,确保依赖引入正确。
二、EntityManagerFactory自动装配失败问题
LocalContainerEntityManagerFactoryBean确实会生成EntityManagerFactory类型的Bean,出现自动装配提示通常有以下原因及解决办法:
1. 自定义Bean未标记@Primary,与自动配置的Bean冲突
Spring Boot3会自动配置默认的EntityManagerFactory,如果你自定义了该Bean,需要给自定义Bean添加@Primary注解,确保自动装配时优先选择你的实现:
@Bean @Primary public LocalContainerEntityManagerFactoryBean entityManagerFactory(DataSource dataSource) { LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean(); em.setDataSource(dataSource); em.setPackagesToScan("com.yourpackage.entity"); // 其他配置... return em; }
2. 注入时未指定Bean名称(多实例场景)
如果项目中有多个EntityManagerFactory Bean,注入时需要通过@Qualifier指定自定义Bean的名称:
@Autowired @Qualifier("entityManagerFactory") // 对应自定义Bean的方法名 private EntityManagerFactory entityManagerFactory;
3. 排除自动配置的JPA类避免冲突
若不需要Spring Boot的自动JPA配置,可在启动类上排除自动配置类:
@SpringBootApplication(exclude = {JpaAutoConfiguration.class}) public class YourApplication { public static void main(String[] args) { SpringApplication.run(YourApplication.class, args); } }
4. 检查LocalContainerEntityManagerFactoryBean配置完整性
确保正确配置数据源、实体扫描包、JPA厂商适配器等核心参数,否则Bean可能无法正常初始化,导致无法被识别为EntityManagerFactory类型:
@Bean @Primary public LocalContainerEntityManagerFactoryBean entityManagerFactory(DataSource dataSource) { LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean(); em.setDataSource(dataSource); em.setPackagesToScan("com.yourpackage.entity"); HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter(); em.setJpaVendorAdapter(vendorAdapter); Properties jpaProperties = new Properties(); jpaProperties.setProperty("hibernate.hbm2ddl.auto", "update"); jpaProperties.setProperty("hibernate.dialect", "org.hibernate.dialect.MySQL8Dialect"); // 替换命名策略 jpaProperties.setProperty("hibernate.physical_naming_strategy", CamelCaseToUnderscoresNamingStrategy.class.getName()); em.setJpaProperties(jpaProperties); return em; }
三、JpaTransactionManager的配套调整
最后,确保JpaTransactionManager正确关联自定义的EntityManagerFactory:
@Bean public PlatformTransactionManager transactionManager(@Qualifier("entityManagerFactory") EntityManagerFactory entityManagerFactory) { JpaTransactionManager transactionManager = new JpaTransactionManager(); transactionManager.setEntityManagerFactory(entityManagerFactory); return transactionManager; }
内容的提问来源于stack exchange,提问作者tafli

