How to setup multiple data sources with Spring and JPA

Hoo :

In our application, we want to set multiple data source with Spring and JPA. Hence we have created 2 entityManagerFactory, 2 data source and 2 transaction- manager.

web.xml

 <param-value>
    /WEB-INF/a_spring.xml
    /WEB-INF/b_spring.xml
 </param-value>

Persistence.xml

<?xml version="1.0" encoding="UTF-8"?>
<persistence version="1.0" xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd">
    <persistence-unit name="db1" transaction-type="RESOURCE_LOCAL">
        <class>com.rh.domain.RcA</class>
    </persistence-unit>

      <persistence-unit name="db2" transaction-type="RESOURCE_LOCAL">
      <class>com.rh.domain.Rcb</class>
    </persistence-unit>
</persistence>

a_spring.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"
           xmlns:tx="http://www.springframework.org/schema/tx" 
           xmlns:aop="http://www.springframework.org/schema/aop"
           xsi:schemaLocation="http://www.springframework.org/schema/beans
           http://www.springframework.org/schema/beans/spring-beans.xsd
           http://www.springframework.org/schema/tx
           http://www.springframework.org/schema/tx/spring-tx-2.0.xsd
           http://www.springframework.org/schema/aop
           http://www.springframework.org/schema/aop/spring-aop-2.0.xsd">

      <bean class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor"/>  
      <bean id = "RcMaintenanceService" class="com.rh.services.RcAbcMaintenanceServiceImpl" autowire="byName" />

    <aop:config>
            <aop:pointcut id="rOperation" expression="execution(* com.rh.services.*.*(..))"/>
            <aop:advisor advice-ref="txAdvice" pointcut-ref="rOperation"/>
        </aop:config>

    <tx:advice id="txAdvice" transaction-manager="transactionManager">
            <tx:attributes>
                   <tx:method name="*"/>
            </tx:attributes>
        </tx:advice>

    <bean id="dataSource" class="org.springframework.jndi.JndiObjectFactoryBean">
            <property name="jndiName" value="java:comp/env/jdbc/db1" />
        </bean> 
        <bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
            <property name="entityManagerFactory" ref="entityManagerFactory"/>
            <property name="dataSource" ref="dataSource"/>
        </bean>

        <bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
               <property name="persistenceUnitName" value="db1" />     
            <property name="dataSource" ref="dataSource"/>
            <property name="jpaVendorAdapter">
                <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter"> 
                    <property name="showSql" value="true"/>
                    <property name="generateDdl" value="false"/>
                    <property name="database" value="MYSQL" />
                    <property name="databasePlatform" value="org.hibernate.dialect.MySQL5Dialect"/>
                </bean>
            </property>
            <property name="jpaDialect">
                <bean class="org.springframework.orm.jpa.vendor.HibernateJpaDialect">
                </bean>
            </property>
        </bean>

I also declare another entityManagetFactory,Transaction Manager and dataSource to b_spring.xml.

Error

Initialization of bean failed; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No unique bean of type [javax.persistence.EntityManagerFactory] is defined: expected single bean but found 2 Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No unique bean of type [javax.persistence.EntityManagerFactory] is defined: expected single bean but found 2 at org.springframework.beans.factory.BeanFactoryUtils.beanOfTypeIncludingAncestors(BeanFactoryUtils.java:303) at org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor.findDefaultEntityManagerFactory(PersistenceAnnotationBeanPostProcessor.java:451) at org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor.findEntityManagerFactory(PersistenceAnnotationBeanPostProcessor.java:428) at org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor$AnnotatedMember.resolveEntityManager(PersistenceAnnotationBeanPostProcessor.java:582) at org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor$AnnotatedMember.resolve(PersistenceAnnotationBeanPostProcessor.java:553) at org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor$AnnotatedMember.inject(PersistenceAnnotationBeanPostProcessor.java:489)

lucid :

In case of multiple data source configuration, we need to define which one will be considered as a primary data source. we can specify that using @Primary annotation in java config or primary=true in XML bean config.

As there is two entity manager being created in XML, we need to use @Qualifier to specify which bean should be injected where. In your case, something like this.

@PersistenceContext(unitName = "db1")
public void setEntityManager(@Qualifier("entityManagerFactory") EntityManager entityMgr) {
    this.em = entityMgr;
}

for XML configuration, we can do something like this

<bean id="BaseService" class="x.y.z.BaseService">
    <property name="em" ref="entityManagerFactory"/>
    <property name="em1" ref="entityManagerFactory1"/>
</bean>

<bean id = "RcMaintenanceService" class="com.rh.services.RcAbcMaintenanceServiceImpl" autowire="byName" parent="BaseService"/>

Guess you like

Origin http://10.200.1.11:23101/article/api/json?id=431254&siteId=1