Goal: Access multiple persistence units / datasources via @PersistenceContext.
Problem: Not fluent in spring xml configurations. Registering multiple datasources appears to require multiple EntityManagerFactories, which then leads to an error, stating that EntityManagerFactory isn't unique. I tried two EntityManagerFactories with an abstract parent one, because I can't add multiple datasources instead of the single datasource in the entityManagerFactory definition. How can I fix this?
I can't use SpringBoot or JpaRepositories. Spring-jdbc and orm are used with version 4.3.4.RELEASE, spring-data-jpa with version 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
The current path from service to database consists of the following files. Note that this only shows the try for one datasource. Another one will be added once the error above is resolved.
Dao:
public class Dao {
@PersistenceContext(name= "puName") // tried unitName=... as well
protected EntityManager em;
...
Test that uses the 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;
...
beans-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>
Update:
I tried adding @Qualifier but I still the NoUniqueBeanDefinitionException ... expected single matching bean but found 2: entityManagerFactory,entityManagerFactory-2.
@PersistenceContext(name = "puName")
@Qualifier("entityManagerFactory")
protected EntityManager em;
Update:
Extending the spring-config with component scan does not change the error.
beans-config.xml:
<context:component-scan annotation-config="true" base-package="path.to.package"/>
<import resource="db-context.xml"/>
Update: Method injection instead of field injection doesn't change the error.