如何使用JPA的EntityManager配置多MySQL数据库?
尝试使用EntityManager连接两个MySQL数据库,此前用Hibernate成功配置过多库,但通过@PersistenceContext(unitName = "foo")注入EntityManager时失败。
现有XML配置:
<bean name="configds" class="org.springframework.jdbc.datasource.DriverManagerDataSource"> <property name="driverClassName" value="${driverClassName}" /> <property name="url" value="${configUrl}" /> <property name="username" value="${configName}" /> <property name="password" value="${configPass}" /> </bean> <bean class="org.springframework.orm.hibernate5.LocalSessionFactoryBean" name="configFac"> <property name="dataSource" ref="configds" /> <property name="hibernateProperties"> <props> <prop key="hibernate.dialect">org.hibernate.dialect.MySQL57Dialect</prop> <prop key="hibernate.dialect">org.hibernate.dialect.MySQL8Dialect</prop> <prop key="hibernate.show_sql">false</prop> <prop key="hibernate.hbm2ddl.auto">none</prop> </props> </property> <property name="packagesToScan"> <list> <value>com.visa.entities</value> </list> </property> </bean> <bean name="configTemp" class="org.springframework.orm.hibernate5.HibernateTemplate"> <property name="sessionFactory" ref="configFac" /> </bean> <bean name="configTxn" class="org.springframework.orm.hibernate5.HibernateTransactionManager"> <property name="sessionFactory" ref="configFac" /> </bean> <!--__________________________________________ DB for visa_slovakia ______________________________________________--> <bean name="svkds" class="org.springframework.jdbc.datasource.DriverManagerDataSource"> <property name="driverClassName" value="${driverClassName}" /> <property name="url" value="${svkUrl}" /> <property name="username" value="${svkName}" /> <property name="password" value="${svkPass}" /> </bean> <bean class="org.springframework.orm.hibernate5.LocalSessionFactoryBean" name="svkFac"> <property name="dataSource" ref="svkds" /> <property name="hibernateProperties"> <props> <prop key="hibernate.dialect">org.hibernate.dialect.MySQL57Dialect</prop> <prop key="hibernate.dialect">org.hibernate.dialect.MySQL8Dialect</prop> <prop key="hibernate.show_sql">false</prop> <prop key="hibernate.hbm2ddl.auto">none</prop> </props> </property> <property name="packagesToScan"> <list> <value>com.visa.entities</value> </list> </property> </bean> <bean name="svkTemp" class="org.springframework.orm.hibernate5.HibernateTemplate"> <property name="sessionFactory" ref="svkFac" /> </bean> <bean name="svkTxn" class="org.springframework.orm.hibernate5.HibernateTransactionManager"> <property name="sessionFactory" ref="svkFac" /> </bean>
DAO层注入代码:
@PersistenceContext(unitName = "configTemp") private EntityManager configTmp; @PersistenceContext(unitName = "svkTemp") private EntityManager svkTmp;
报错信息:
org.springframework.beans.factory.BeanNotOfRequiredTypeException: Bean named 'configTemp' is expected to be of type 'javax.persistence.EntityManagerFactory' but was actually of type 'org.springframework.orm.hibernate5.HibernateTemplate'
1. 替换HibernateTemplate为EntityManagerFactory配置
@PersistenceContext的unitName需要指向EntityManagerFactory类型的bean,而非HibernateTemplate。你需要为每个数据库配置LocalContainerEntityManagerFactoryBean,同时更新事务管理器为JPA类型。
修改XML配置:
删除原有HibernateTemplate bean,新增两个EntityManagerFactory及对应事务管理器:
<!-- 第一个数据库的EntityManagerFactory --> <bean id="configEntityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"> <property name="dataSource" ref="configds"/> <property name="packagesToScan" value="com.visa.entities"/> <property name="jpaVendorAdapter"> <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter"/> </property> <property name="jpaProperties"> <props> <prop key="hibernate.dialect">org.hibernate.dialect.MySQL8Dialect</prop> <prop key="hibernate.show_sql">false</prop> <prop key="hibernate.hbm2ddl.auto">none</prop> </props> </property> </bean> <!-- 第二个数据库的EntityManagerFactory --> <bean id="svkEntityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"> <property name="dataSource" ref="svkds"/> <property name="packagesToScan" value="com.visa.entities"/> <property name="jpaVendorAdapter"> <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter"/> </property> <property name="jpaProperties"> <props> <prop key="hibernate.dialect">org.hibernate.dialect.MySQL8Dialect</prop> <prop key="hibernate.show_sql">false</prop> <prop key="hibernate.hbm2ddl.auto">none</prop> </props> </property> </bean> <!-- 第一个数据库的事务管理器 --> <bean id="configTxn" class="org.springframework.orm.jpa.JpaTransactionManager"> <property name="entityManagerFactory" ref="configEntityManagerFactory"/> </bean> <!-- 第二个数据库的事务管理器 --> <bean id="svkTxn" class="org.springframework.orm.jpa.JpaTransactionManager"> <property name="entityManagerFactory" ref="svkEntityManagerFactory"/> </bean>
注意:原配置重复设置
hibernate.dialect,保留一个适配你MySQL版本的即可,建议用MySQL8Dialect。
2. 修正DAO层注入
将@PersistenceContext的unitName指向新配置的EntityManagerFactory的bean id:
@PersistenceContext(unitName = "configEntityManagerFactory") private EntityManager configTmp; @PersistenceContext(unitName = "svkEntityManagerFactory") private EntityManager svkTmp;
3. 可选:保留原有SessionFactory的方案
如果不想完全替换为JPA配置,可通过现有SessionFactory包装出EntityManagerFactory,新增如下bean:
<bean id="configEntityManagerFactory" factory-bean="configFac" factory-method="getObject"/> <bean id="svkEntityManagerFactory" factory-bean="svkFac" factory-method="getObject"/>
之后同样更新事务管理器和DAO注入即可。
内容的提问来源于stack exchange,提问作者Akhilesh Dhiman

