Spring 6(Spring Boot3.1)迁移多数据源EntityManager初始化异常排查
问题排查与解决方案
核心问题分析
Cannot resolve reference to bean 'entityManagerFactory':Spring Data 默认会查找名为entityManagerFactory或标记为主bean的EntityManagerFactory实例,但你的配置中只有firstEMF和secondEMF,没有指定主bean,导致容器无法确定默认实例。The application must supply JDBC connections:EntityManagerFactory构建阶段数据源为空,大概率是EMF与DataSource的绑定配置不完整,或Hibernate版本与Spring 6不兼容导致的初始化顺序问题。
分步解决
1. 配置主EntityManagerFactory(解决默认bean找不到的问题)
在XML配置中,给其中一个LocalContainerEntityManagerFactoryBean添加primary="true"属性,指定它作为Spring Data的默认实例:
<!-- 第一个EntityManagerFactory,标记为主bean --> <bean id="firstEMF" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean" primary="true"> <property name="dataSource" ref="firstDataSource"/> <property name="packagesToScan" value="com.yourproject.first.entity"/> <property name="persistenceUnitName" value="firstPersistenceUnit"/> <!-- JPA供应商适配器,必须适配Spring 6的Hibernate 6.x版本 --> <property name="jpaVendorAdapter"> <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter"> <property name="showSql" value="true"/> <property name="generateDdl" value="true"/> <property name="databasePlatform" value="org.hibernate.dialect.MySQL8Dialect"/> <!-- 对应你的数据库方言 --> </bean> </property> <property name="jpaProperties"> <props> <prop key="hibernate.hbm2ddl.auto">update</prop> </props> </property> </bean> <!-- 第二个EntityManagerFactory --> <bean id="secondEMF" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"> <property name="dataSource" ref="secondDataSource"/> <property name="packagesToScan" value="com.yourproject.second.entity"/> <property name="persistenceUnitName" value="secondPersistenceUnit"/> <property name="jpaVendorAdapter"> <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter"> <property name="showSql" value="true"/> <property name="generateDdl" value="true"/> <property name="databasePlatform" value="org.hibernate.dialect.MySQL8Dialect"/> </bean> </property> </bean>
2. 确保DataSource配置正确(解决数据源为空问题)
检查DataSource的属性配置,Spring 6+与Java 17要求数据库驱动类必须为当前版本的合规类(比如MySQL需用com.mysql.cj.jdbc.Driver,而非旧版的com.mysql.jdbc.Driver):
<bean id="firstDataSource" class="com.zaxxer.hikari.HikariDataSource"> <property name="driverClassName" value="com.mysql.cj.jdbc.Driver"/> <property name="jdbcUrl" value="${first.datasource.url}"/> <property name="username" value="${first.datasource.username}"/> <property name="password" value="${first.datasource.password}"/> </bean> <bean id="secondDataSource" class="com.zaxxer.hikari.HikariDataSource"> <property name="driverClassName" value="com.mysql.cj.jdbc.Driver"/> <property name="jdbcUrl" value="${second.datasource.url}"/> <property name="username" value="${second.datasource.username}"/> <property name="password" value="${second.datasource.password}"/> </bean>
3. 绑定事务管理器
为每个EntityManagerFactory配置独立的事务管理器,避免事务上下文混乱:
<bean id="firstTxManager" class="org.springframework.orm.jpa.JpaTransactionManager"> <property name="entityManagerFactory" ref="firstEMF"/> </bean> <bean id="secondTxManager" class="org.springframework.orm.jpa.JpaTransactionManager"> <property name="entityManagerFactory" ref="secondEMF"/> </bean>
4. DAO层注入规范
确保DAO层注入时明确指定目标EntityManagerFactory,避免歧义:
@Autowired @Qualifier("firstEMF") // 对应XML中的bean id private EntityManagerFactory entityManagerFactory; // 或直接注入EntityManager,指定持久化单元名 @PersistenceContext(unitName = "firstPersistenceUnit") private EntityManager entityManager;
5. 依赖版本适配
Spring Boot 3.1默认依赖Hibernate 6.x,必须确保你的项目中没有引入旧版Hibernate依赖。如果是自定义依赖,需将Hibernate版本升级至6.2.x及以上。
内容的提问来源于stack exchange,提问作者rbrbrts
相关产品推荐
相关产品推荐

