spring-data-jpa 如何使用多个数据源? [复制]

Posted

技术标签:

【中文标题】spring-data-jpa 如何使用多个数据源? [复制]【英文标题】:how to use multiple datasources with spring-data-jpa? [duplicate] 【发布时间】:2015-09-07 20:58:21 【问题描述】:

我阅读了所有相关问题并尝试了所有问题,但仍然无法正确配置。

我有两个数据库,我想将它们用作我的应用程序中的数据源。

这是我的上下文文件:

<jee:jndi-lookup id="firstDataSource" jndi-name="java:/comp/env/jdbc/firstDS"   expected-type="javax.sql.DataSource" />
<jee:jndi-lookup id="secondDataSource" jndi-name="java:/comp/env/jdbc/secondDS" expected-type="javax.sql.DataSource" />

<bean name="persistenceProvider" class="org.hibernate.jpa.HibernatePersistenceProvider"></bean>

<bean class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean" id="thisEntityManagerFactory">
    <property name="dataSource" ref="firstDataSource"/>
    <property name="packagesToScan" value="com.a.b.first.model"/>
    <property name="jpaVendorAdapter">
        <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
            <property name="generateDdl" value="false" />
            <property name="showSql" value="true"/>
            <property name="databasePlatform" value= "org.hibernate.dialect.Oracle10gDialect"/>
            <property name="database" value="ORACLE"/>
        </bean>
    </property>
    <property name="persistenceUnitName" value="firstPersistenceUnit" />
    <property name="persistenceProvider" ref="persistenceProvider"></property>
    <property name="jpaProperties">
        <value>
            hibernate.generate_statistics = true
            hibernate.cache.use_second_level_cache = true
            hibernate.cache.region.factory_class = org.hibernate.cache.ehcache.SingletonEhCacheRegionFactory
            hibernate.cache.use_query_cache = true
            <!--hibernate.hbm2ddl.auto=create-->
        </value>
    </property>
</bean>

<bean class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean" id="otherEntityManagerFactory">
    <property name="dataSource" ref="secondDataSource"/>
    <property name="packagesToScan" value="com.a.b.second.model"/>
    <property name="jpaVendorAdapter">
        <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
            <property name="generateDdl" value="false" />
            <property name="showSql" value="true"/>
            <property name="databasePlatform" value= "org.hibernate.dialect.Oracle10gDialect"/>
            <property name="database" value="ORACLE"/>
        </bean>
    </property>
    <property name="persistenceUnitName" value="secondPersistenceUnit" />
    <property name="persistenceProvider" ref="persistenceProvider"></property>
    <property name="jpaProperties">
        <value>
            hibernate.generate_statistics = true
            hibernate.cache.use_second_level_cache = true
            hibernate.cache.region.factory_class = org.hibernate.cache.ehcache.SingletonEhCacheRegionFactory
            hibernate.cache.use_query_cache = true
            <!--hibernate.hbm2ddl.auto=create-->
        </value>
    </property>
</bean>

<bean class="org.springframework.orm.jpa.JpaTransactionManager" id="thisTransactionManager">
    <property name="entityManagerFactory" ref="thisEntityManagerFactory"/>
    <property name="jpaDialect">
        <bean class="org.springframework.orm.jpa.vendor.HibernateJpaDialect" />
    </property>
</bean>

<bean class="org.springframework.orm.jpa.JpaTransactionManager" id="otherTransactionManager">
    <property name="entityManagerFactory" ref="otherEntityManagerFactory"/>
    <property name="jpaDialect">
        <bean class="org.springframework.orm.jpa.vendor.HibernateJpaDialect" />
    </property>
</bean>

<tx:annotation-driven transaction-manager="thisTransactionManager" />

<tx:annotation-driven transaction-manager="otherTransactionManager" />

<jpa:repositories base-package="com.a.b.first.intf" entity-manager-factory-ref="thisEntityManagerFactory" transaction-manager-ref="transactionManager"/>
<jpa:repositories base-package="com.a.b.second.intf" entity-manager-factory-ref="otherEntityManagerFactory" transaction-manager-ref="otherTransactionManager" />

问题是当我尝试使用位于包 com.absecond.intf 下的存储库接口时,它会转到 firstDataSource 并抛出带有消息“的 SQLSyntaxErrorException” ORA-00942: 表或视图不存在”。因为第一个数据库中没有这样的表。

每个EntityManagerFactory的日志中都有一行,说

为持久化单元构建 JPA 容器 EntityManagerFactory '默认'

在下一行中,它为这个 EntityManagerFactory 打印 PersistenceUnitInfo。 PersistenceUnitInfo 的“非 JTA 数据源”属性对于两个 EntityManagerFactories 是相同的。我猜这意味着两个持久性单元使用相同的数据源。

我错过了什么?

谢谢。

【问题讨论】:

baeldung.com/spring-data-jpa-multiple-databases @RobertNiestroj 我认为我的 xml 配置是相同的。或者我遗漏了一些小细节。你能看看我的配置吗? 原来问题出在我的 context.xml 文件中。 &lt;ResourceLink name="jdbc/firstDS" global="jdbc/firstDS" type="javax.sql.DataSource"/&gt; &lt;ResourceLink name="jdbc/secondDS" global="jdbc/firstDS" type="javax.sql.DataSource"/&gt; 第二个数据源的全局属性指向第一个数据源。因此,每次我进行 jndi 查找时,它都会得到错误的数据源。傻瓜复制粘贴错误。 【参考方案1】:

在你的服务层你应该有这样的东西:

@Service
@Transactional("thisTransactionManager")
public class ThisService

   @Autowired
   private com.a.b.first.intf.Repo1 repo1;


@Service
@Transactional("otherEntityManagerFactory")
public class OtherService

   @Autowired
   private com.a.b.second.intf.Repo1 repo1;

这样,当您调用服务方法时,TransactionInterceptor 可以加载相应的事务管理器,关联到您要操作的EntityManagerFactory

【讨论】:

Vlad Mihalcea 我试过了,还是一样的例外。我认为这里的问题不在于选择正确的 EntityManagerFactory。创建第二个 EntityManagerFactory 时,它的持久化单元获取了错误的数据源。 这很奇怪,因为您指定了LocalContainerEntityManagerFactoryBeandataSource 属性。尝试在 LocalContainerEntityManagerFactoryBean 中添加一个断点,看看它是否加载了正确的 DataSource。

以上是关于spring-data-jpa 如何使用多个数据源? [复制]的主要内容,如果未能解决你的问题,请参考以下文章

使用 spring-data-jpa 和 spring-mvc 过滤数据库行

如何禁用嵌入式数据库 Spring-boot spring-data-jpa

spring-data-jpa实体类继承抽象类如何映射父类的属性到数据库

从控制台应用程序使用带有休眠功能的spring-data-jpa时如何延迟加载收集

如何使用 spring4+spring-data-jpa(hibernateJpaVendorAdapter)+multidatasource+one entityManager+jpaReposit

springboot多数据源配置