目标:通过@PersistenceContext
访问多个持久性单元/数据源。
问题:Spring xml配置不流畅。注册多个数据源似乎需要多个EntityManagerFactories,然后导致错误,说明EntityManagerFactory不是唯一的。我尝试了两个带有抽象父类的EntityManagerFactories,因为我无法在entityManagerFactory定义中添加多个数据源 s 而不是单个数据源。我该如何解决这个问题?
我无法使用SpringBoot或JpaRepositories。 Spring-jdbc和orm与4.3.4.RELEASE版本一起使用,spring-data-jpa版本为1.10.5.RELEASE。
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'aDaoImpl': Injection of persistence dependencies failed; nested exception is org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type 'javax.persistence.EntityManagerFactory' available: expected single matching bean but found 2: entityManagerFactory,entityManagerFactory-2
at org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor.postProcessPropertyValues(PersistenceAnnotationBeanPostProcessor.java:357)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1219)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:551)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:482)
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:306)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:302)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:754)
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:866)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:542)
at org.springframework.test.context.support.AbstractGenericContextLoader.loadContext(AbstractGenericContextLoader.java:128)
at org.springframework.test.context.support.AbstractGenericContextLoader.loadContext(AbstractGenericContextLoader.java:60)
at org.springframework.test.context.support.AbstractDelegatingSmartContextLoader.delegateLoading(AbstractDelegatingSmartContextLoader.java:108)
at org.springframework.test.context.support.AbstractDelegatingSmartContextLoader.loadContext(AbstractDelegatingSmartContextLoader.java:251)
at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContextInternal(DefaultCacheAwareContextLoaderDelegate.java:98)
at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:116)
... 24 more
Caused by: org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type 'javax.persistence.EntityManagerFactory' available: expected single matching bean but found 2: entityManagerFactory,entityManagerFactory-2
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveNamedBean(DefaultListableBeanFactory.java:1034)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveNamedBean(DefaultListableBeanFactory.java:981)
at org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor.findDefaultEntityManagerFactory(PersistenceAnnotationBeanPostProcessor.java:579)
at org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor.findEntityManagerFactory(PersistenceAnnotationBeanPostProcessor.java:546)
at org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor$PersistenceElement.resolveEntityManager(PersistenceAnnotationBeanPostProcessor.java:707)
at org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor$PersistenceElement.getResourceToInject(PersistenceAnnotationBeanPostProcessor.java:680)
at org.springframework.beans.factory.annotation.InjectionMetadata$InjectedElement.inject(InjectionMetadata.java:169)
at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:88)
at org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor.postProcessPropertyValues(PersistenceAnnotationBeanPostProcessor.java:354)
... 40 more
从服务到数据库的当前路径包含以下文件。请注意,这仅显示一个数据源的尝试。一旦上述错误得到解决,将添加另一个。
道:
public class Dao {
@PersistenceContext(name= "puName") // tried unitName=... as well
protected EntityManager em;
...
使用Dao的测试:
@ContextConfiguration("classpath:beans-context.xml")
public class DaoTest extends AbstractTransactionalJUnit4SpringContextTests {
@Autowired
private Dao testable;
@PersistenceContext(name= "puName") // tried unitName=... as well
protected EntityManager em;
...
豆-config.xml中:
...
<import resource="db-context.xml"/>
...
DB-context.xml中:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.3.xsd">
<bean id="dataSource1" class="org.apache.commons.dbcp.BasicDataSource">
<property name="driverClassName" value="org.h2.Driver"/>
<property name="url" value="jdbc:h2:mem:test;DB_CLOSE_DELAY=-1"/>
<property name="username" value="sa"/>
<property name="password" value=""/>
</bean>
<bean id="dataSource2" class="org.apache.commons.dbcp.BasicDataSource">
<property name="driverClassName" value="org.h2.Driver"/>
<property name="url" value="jdbc:h2:mem:test2;DB_CLOSE_DELAY=-1"/>
<property name="username" value="sa"/>
<property name="password" value=""/>
</bean>
<bean id="entityManagerFactory" parent="abstractEntityManagerFactory">
<property name="dataSource" ref="dataSource1"/>
<property name="persistenceUnitName" value="puName"/>
</bean>
<!-- this causes the NoUniqueBeanDefinitionException -->
<bean id="entityManagerFactory-2" parent="abstractEntityManagerFactory">
<property name="dataSource" ref="dataSource2"/>
<property name="persistenceUnitName" value="puName2"/>
</bean>
<bean id="abstractEntityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"
abstract="true">
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
<property name="databasePlatform" value="org.hibernate.dialect.H2Dialect"/>
</bean>
</property>
</bean>
<bean class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor"/>
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager"/>
</beans>
更新:
我尝试添加@Qualifier
,但我仍然是NoUniqueBeanDefinitionException ... expected single matching bean but found 2: entityManagerFactory,entityManagerFactory-2
。
@PersistenceContext(name = "puName")
@Qualifier("entityManagerFactory")
protected EntityManager em;
更新:
使用组件扫描扩展spring-config不会更改错误。
豆-config.xml中:
<context:component-scan annotation-config="true" base-package="path.to.package"/>
<import resource="db-context.xml"/>
更新: 方法注入而不是字段注入不会改变错误。
答案 0 :(得分:2)
您的代码包含两个含糊之处:
@PersistenceContext
的单位分辨率。JpaTransactionManager
的单位分辨率。解决@PersistenceContext
使用的歧义
@PersistenceContext(unitName = …)
代替@PersistenceContext(name = …)
@PersistenceContext(unitName = "puName")
protected EntityManager em1;
@PersistenceContext(unitName = "puName2")
protected EntityManager em2;
JpaTransactionManager
还需要提示,否则初始化将失败
Caused by: org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type 'javax.persistence.EntityManagerFactory' available: expected single matching bean but found 2: entityManagerFactory,entityManagerFactory-2
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveNamedBean(DefaultListableBeanFactory.java:1034)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBean(DefaultListableBeanFactory.java:340)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBean(DefaultListableBeanFactory.java:335)
at org.springframework.orm.jpa.EntityManagerFactoryUtils.findEntityManagerFactory(EntityManagerFactoryUtils.java:143)
at org.springframework.orm.jpa.JpaTransactionManager.setBeanFactory(JpaTransactionManager.java:292)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeAwareMethods(AbstractAutowireCapableBeanFactory.java:1602)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1570)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:553)
... 38 more
因此,解决歧义的一种方法是设置persistenceUnitName
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="persistenceUnitName" value="puName" />
</bean>