multiple databases with Spring Data JPA

烈酒焚心 提交于 2019-12-23 02:24:07

问题


I'm trying to use Spring Data JPA with 2 databases in project. But an exception is triggered when I'm trying to run the application:

07:21:47.734 [main] ERROR o.s.web.context.ContextLoader - Context initialization failed
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'deviceRepository': Injection of persistence dependencies 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
    at org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor.postProcessPropertyValues(PersistenceAnnotationBeanPostProcessor.java:342) ~[spring-orm-3.1.0.RELEASE.jar:3.1.0.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1106) ~[spring-beans-3.1.0.RELEASE.jar:3.1.0.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:517) ~[spring-beans-3.1.0.RELEASE.jar:3.1.0.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:456) ~[spring-beans-3.1.0.RELEASE.jar:3.1.0.RELEASE]
    at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:294) ~[spring-beans-3.1.0.RELEASE.jar:3.1.0.RELEASE]
...

Here is my applicationContext.xml

<bean class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close" id="dataSource1">
    <property name="driverClassName" value="${database.driverClassName}"/>
    <property name="url" value="${database.url1}"/>
    <property name="username" value="${database.username1}"/>
    <property name="password" value="${database.password1}"/>
    <property name="testOnBorrow" value="true"/>
    <property name="testOnReturn" value="true"/>
    <property name="testWhileIdle" value="true"/>
    <property name="timeBetweenEvictionRunsMillis" value="1800000"/>
    <property name="numTestsPerEvictionRun" value="3"/>
    <property name="minEvictableIdleTimeMillis" value="1800000"/>
    <property name="validationQuery" value="SELECT 1"/>
</bean>
<bean class="org.springframework.orm.jpa.JpaTransactionManager" id="transactionManager1">
    <property name="entityManagerFactory" ref="entityManagerFactory1"/>
</bean>
<tx:annotation-driven mode="aspectj" transaction-manager="transactionManager1"/>
<bean class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean" id="entityManagerFactory1">
    <property name="persistenceUnitName" value="persistenceUnit1"/>
    <property name="dataSource" ref="dataSource1"/>
</bean>

<bean class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close" id="dataSource2">
    <property name="driverClassName" value="${database.driverClassName}"/>
    <property name="url" value="${database.url2}"/>
    <property name="username" value="${database.username2}"/>
    <property name="password" value="${database.password2}"/>
    <property name="testOnBorrow" value="true"/>
    <property name="testOnReturn" value="true"/>
    <property name="testWhileIdle" value="true"/>
    <property name="timeBetweenEvictionRunsMillis" value="1800000"/>
    <property name="numTestsPerEvictionRun" value="3"/>
    <property name="minEvictableIdleTimeMillis" value="1800000"/>
    <property name="validationQuery" value="SELECT 1"/>
</bean>
<bean class="org.springframework.orm.jpa.JpaTransactionManager" id="transactionManager2">
    <property name="entityManagerFactory" ref="entityManagerFactory2"/>
</bean>
<tx:annotation-driven mode="aspectj" transaction-manager="transactionManager2"/>
<bean class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean" id="entityManagerFactory2">
    <property name="persistenceUnitName" value="persistenceUnit2"/>
    <property name="dataSource" ref="dataSource2"/>
</bean>

Here is my DAO interface:

@Repository
public interface DeviceRepository extends JpaRepository<Device, DevicePK>,
    JpaSpecificationExecutor<Device> {
}

I've read a lot about @PersistenceContext but I never saw usages with JpaRepository.


回答1:


Well you do have 2 entitymanagers. I've never used JPARepository, but if it works close to its counter parts on spring-data for nosql, Spring will enhance the class, and probably inject the EM on it. Your problem is that you have 2 EM declared.

Have a look at the spring-jpa docs, they'll show you how to configure the repository for how you can add specific EMF to your repos




回答2:


Long story short:

You have to create custom implementation of that interface and that implementation has to contain entity manager declared as:

    @PersistenceContext(unitName = "persistenceUnit1")
    private EntityManager entityManager;

if you want to use persistence unit 1.

Check this out: http://docs.spring.io/spring-data/data-jpa/docs/current/reference/html/repositories.html#repositories.custom-implementations, it also has examples and example 1.17 (little bit down the page) implements interface and has entity manager in it and that entity manager is passed on to super constructor.

You may also take a look at Spring Data - JPA, customizing Repository not working, it has implementation of interface that extends JpaRepository and it also has entity manager declared in implementation. Just add unitName to @PersistenceContext annotation and try it that way.

You may not need any custom methods (so your interface can be empty) but you do need constructor that passes on entity manager and all that tinkering with extending your own interface to bypass default automatic wiring behaviour.




回答3:


One of the two datasource must be defined as primary.

<bean> has a primary attribute that can be set to true or false:

<bean primary="true|false"/>

Usually in @Configuration the @Primary annotation is placed to:

EntityManager DataSource TransactionManager

So you can try to add primary="true"

to the following beans:

dataSource1 transactionManager1 entityManagerFactory1



来源:https://stackoverflow.com/questions/9893274/multiple-databases-with-spring-data-jpa

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!