当前位置: 首页 > 知识库问答 >
问题:

Spring 通过 XML Bean-definition 注册多个Hibernate数据源

祝昊东
2023-03-14

目标: 通过@PersistenceContext访问多个持久性单元/数据源。

问题:在 Spring xml 配置中不流畅。注册多个数据源似乎需要多个 EntityManagerFactory,这会导致错误,指出 EntityManagerFactory 不是唯一的。我尝试了两个带有抽象父级的实体管理器工厂,因为我无法在实体管理器工厂定义中添加多个数据源而不是单个数据源。我该如何解决这个问题?

我不能使用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;

    ...

使用道的测试:

@ContextConfiguration("classpath:beans-context.xml")
public class DaoTest extends AbstractTransactionalJUnit4SpringContextTests {

    @Autowired
    private Dao testable;

    @PersistenceContext(name= "puName") // tried unitName=... as well
    protected EntityManager em;

    ...

bean-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...预期单个匹配的 bean,但找到 2:实体管理器工厂,实体管理器工厂-2

@PersistenceContext(name = "puName")
@Qualifier("entityManagerFactory")
protected EntityManager em;

更新:

使用组件扫描扩展Spring配置不会改变错误。

bean-config . XML:

<context:component-scan annotation-config="true" base-package="path.to.package"/>
<import resource="db-context.xml"/>

更新:方法注入而不是字段注入不会更改错误。

共有1个答案

苏季同
2023-03-14

您的代码包含两个歧义:

  1. @Per一致上下文的单元分辨率。
  2. JpaTransactionManager的单元分辨率。

若要解决< code>@PersistenceContext的二义性,请使用< code > @ persistence context(unitName =…)而不是< code > @ persistence context(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

因此,解决歧义的一种方法是设置持久性单位名称

<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
    <property name="persistenceUnitName" value="puName" />
</bean>
 类似资料:
  • 问题内容: 我有一个Spring + Hibernate + JPA应用程序。用户登录时,可以从要连接的数据库列表中进行选择(这是要求)。所有数据库都有相同的架构,因此将使用相同的实体和DAO。 现在,我有一个EntityManager(目前正在使用一个数据库),它被注入到DAO中,如下所示: 有什么方法可以让DAO根据从服务层接收到的参数/属性自动接收entityManager(由Spring管

  • 问题内容: 我有hibernate通过JNDI数据源连接到数据库。 我的目的:使用JNDI注册数据源以测试DAO层。 例 hibernate配置 在测试类中获取SessionFactory: 作为结果: 要注册JNOI,我使用示例(http://www.roseindia.net/tutorial/java/jdbc/registeringthedatasourcewithjndi.html) 请

  • 问题内容: 我正在编写一个支持多个用户的Web应用程序。每个用户都有自己的数据库-使用H2。所有数据库架构都是相同的。 我希望将Spring + Hibernate用于此应用程序。 因此,我坚持如何将用户的数据库与该用户相关联- 也许将其与HTTPSession关联,并扩展spring的AbstractRoutingDataSource?但这不会影响Hibernate的缓存吗?另一种方法是为每个数

  • 问题内容: 我正在尝试配置Spring + Hibernate + JPA以使用两个数据库(MySQL和MSSQL)。 我的datasource-context.xml: 每个persistence.xml包含一个单元,如下所示: PersistenceUnitManager导致以下异常: 如果只留下一个没有列表的persistence.xml,则每个列表都可以正常工作,但我需要2个单元… 我还尝

  • 有一些示例可以使用多个数据源: 但他们不使用实体管理器。是否有可能得到这样的东西: 谢了。

  • 问题内容: 我使用我的uuid如下: 但是我收到了一个聪明的Hibernate警告: 使用org.hibernate.id.UUIDHexGenerator不会生成符合IETF RFC 4122的UUID值;考虑改用org.hibernate.id.UUIDGenerator 所以我想切换到,现在我的问题是如何将其告知Hibernate的生成器。我看到有人用它作为“hibernateuuid”-这