首页 > 解决方案 > Spring Boot 2.1.7RELEASE-NoUniqueBeanDefinitionException

问题描述

在将 Spring 迁移到 Spring Boot2.1.7 时面临 NoUniqueBeanDefinitionException。Bean 配置是 xml 文件。我们使用 @ImportResources 注释添加了该 xml 文件

/\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::        (v2.1.7.RELEASE)

log4j:WARN Please initialize the log4j system properly.
log4j:WARN See http://logging.apache.org/log4j/1.2/faq.html#noconfig for more info.
62  SybaseUnit  INFO   [main] openjpa.Enhance - You have enabled runtime enhancement, but have not specified the set of persistent classes.  OpenJPA must look for metadata for every loaded class, which might increase class load times significantly.
23  SybaseUnit  WARN   [main] openjpa.Runtime - An error occurred while registering a ClassTransformer with PersistenceUnitInfo: name 'SybaseUnit', root URL [Service/target/classes/]. The error has been consumed. To see it, set your openjpa.Runtime log level to TRACE. Load-time class transformation will not be available.
30  SybaseUnit  WARN   [main] openjpa.Runtime - Could not create the optional validation provider. Reason returned: "A default ValidatorFactory could not be created."
2  MssqlUnit  INFO   [main] openjpa.Enhance - You have enabled runtime enhancement, but have not specified the set of persistent classes.  OpenJPA must look for metadata for every loaded class, which might increase class load times significantly.
1  MssqlUnit  WARN   [main] openjpa.Runtime - An error occurred while registering a ClassTransformer with PersistenceUnitInfo: name 'MssqlUnit', root URL [Service/target/classes/]. The error has been consumed. To see it, set your openjpa.Runtime log level to TRACE. Load-time class transformation will not be available.
2  MssqlUnit  WARN   [main] openjpa.Runtime - Could not create the optional validation provider. Reason returned: "A default ValidatorFactory could not be created."
[WARNING] 
    java.lang.reflect.InvocationTargetException
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:498)
        at org.springframework.boot.maven.AbstractRunMojo$LaunchRunner.run(AbstractRunMojo.java:543)
        at java.lang.Thread.run(Thread.java:748)
    Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'dataAccessService': 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: sybaseEntityManagerFactory,mssqlEntityManagerFactory
        at org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor.postProcessPropertyValues(PersistenceAnnotationBeanPostProcessor.java:357)
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1416)
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:592)
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:515)
        at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:320)
        at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222)
        at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:318)
        at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:199)
        at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:845)
        at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:877)
        at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:549)
        at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:141)
        at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:743)
        at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:390)
        at org.springframework.boot.SpringApplication.run(SpringApplication.java:312)
        at com.ge.hcit.xer.app.services.api.XERServiceMain.main(XERServiceMain.java:41)
        ... 6 more
    Caused by: org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type 'javax.persistence.EntityManagerFactory' available: expected single matching bean but found 2: sybaseEntityManagerFactory,mssqlEntityManagerFactory
        at org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor.findDefaultEntityManagerFactory(PersistenceAnnotationBeanPostProcessor.java:572)
        at org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor.findEntityManagerFactory(PersistenceAnnotationBeanPostProcessor.java:531)
        at org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor$PersistenceElement.resolveEntityManager(PersistenceAnnotationBeanPostProcessor.java:697)
        at org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor$PersistenceElement.getResourceToInject(PersistenceAnnotationBeanPostProcessor.java:670)
        at org.springframework.beans.factory.annotation.InjectionMetadata$InjectedElement.inject(InjectionMetadata.java:180)
        at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:90)
        at org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor.postProcessPropertyValues(PersistenceAnnotationBeanPostProcessor.java:354)
        ... 21 more

XML bean 配置

<bean id="mssqlDataSource" class="org.apache.tomcat.jdbc.pool.DataSource" 
        depends-on="localConfig">

    </bean>

    <bean id="mssqlTransactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
        <property name="entityManagerFactory" ref="mssqlEntityManagerFactory" />

    </bean>


    <bean id="mssqlEntityManagerFactory"
        class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean" primary ="true">
        <property name="dataSource" ref="mssqlDataSource" />
        <property name="jpaVendorAdapter" ref="openJpaVendorAdapter" />
        <property name="persistenceUnitName" value="MssqlUnit" />
        <property name="packagesToScan" >
            <list>
                <value>com.datasource.jpa.dto</value>
            </list>
        </property>
    </bean>

</beans>

<bean id="sybaseDataSource" class="org.apache.tomcat.jdbc.pool.DataSource" 
        depends-on="localConfig">       
    </bean>

    <bean id="sybaseTransactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
        <property name="entityManagerFactory" ref="sybaseEntityManagerFactory" />
         <property name="persistenceUnitName" value="SybaseUnit" />

    </bean>


    <bean id="sybaseEntityManagerFactory"
        class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
        <property name="dataSource" ref="sybaseDataSource" />

    </bean>

还要排除 Spring boot 主类中的 HibernateJpaAutoConfiguration.class 参考以下链接 stackoverflow 链接

数据访问服务

@Repository

public class DataAccessService
{
    private static final Logger LOGGER = Logger.getLogger(DataAccessService.class);

    private static final String DEFAULT_HOSTNAME = "localhost";

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

我如何在 xml 文件配置中做同样的事情

如何在不删除 xml bean 定义的情况下将 bean 设置为“mssqlEntityManagerFactory”。进行以下操作

1.add Primary ="true"
2.add unitName="MssqlUnit"
3.add Qualifer

但仍然得到同样的错误

标签: springspring-bootspring-data-jpaspring-beanspring-orm

解决方案


Spring boot 正在按类型解决依赖关系,它正在为 javax.persistence.EntityManagerFactory 找到两个实现

  1. sybaseEntityManagerFactory
  2. mssqlEntityManagerFactory

您所需要做的就是将您的 bean 之一设置为您想要使用的主要

<bean primary="true|false"/>

像下面

<bean id="mssqlEntityManagerFactory" primary="true" 
        class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
        <property name="dataSource" ref="mssqlDataSource" />
        <property name="jpaVendorAdapter" ref="openJpaVendorAdapter" />
        <property name="persistenceUnitName" value="MssqlUnit" />
        <property name="packagesToScan" >
            <list>
                <value>com.datasource.jpa.dto</value>
            </list>
        </property>
    </bean>

或者您可以有条件地加载一个 bean,此URL可能会对您有所帮助。


推荐阅读