spring - 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
但仍然得到同样的错误
解决方案
Spring boot 正在按类型解决依赖关系,它正在为 javax.persistence.EntityManagerFactory 找到两个实现
- sybaseEntityManagerFactory
- 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可能会对您有所帮助。
推荐阅读
- onedrive - Graph API 订阅通知持续触发
- cuda - 为什么 cudaPointerGetAttributes() 返回主机指针的无效参数?
- java - Apache POI 散点图创建
- react-native - 使用 Instagram API 反应本机应用程序身份验证
- vba - 如何通过 VBA 代码打开现有的 Excel 工作表
- javascript - Amazon API 中的请求签名不匹配(要签名的字符串)
- django - Django 在调用视图方法之前添加访问 URL 的权限
- angular - 以角度 5 更新 routeparams
- c# - 确认中间件正在使用中
- javascript - 导出/Serialzie Google 图表选项