Spring Boot嵌入式Tomcat - 没有'javax.sql.DataSource'类型的限定bean可用:预期单个匹配bean但找到3

问题描述 投票:0回答:2

我正在使用我的spring启动应用程序并使用嵌入式tomcat 8.x运行。我正在尝试使用JNDI配置三个不同的oracle数据源,并遵循此link。以下是我的不同文件:

application-Dev.properties

spring.oracle.datasource.oracleDS1.jndi-name=jdbc/oracleDS1
spring.oracle.datasource.oracleDS2.jndi-name=jdbc/oracleDS2
spring.oracle.datasource.oracleDS3.jndi-name=jdbc/oracleDS3

OracleDataSourceConfiguration

package com.adp.orbis.requesttracker.orbisrequesttracker;

import javax.sql.DataSource;

    import org.springframework.beans.factory.annotation.Qualifier;
    import org.springframework.beans.factory.annotation.Value;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.context.annotation.Primary;
    import org.springframework.context.annotation.Profile;
    import org.springframework.jdbc.core.JdbcTemplate;
    import org.springframework.jdbc.datasource.lookup.JndiDataSourceLookup;

    @Configuration
    public class OracleDataSourceConfiguration {

        @Value("${spring.oracle.datasource.oracleDS1.jndi-name}")
        private String oracleDS1;

        @Value("${spring.oracle.datasource.oracleDS2.jndi-name}")
        private String oracleDS2;

        @Value("${spring.oracle.datasource.oracleDS3.jndi-name}")
        private String oracleDS3;

        @Bean(name="dataSource1", destroyMethod = "")
        @Profile("dev")
        @Primary
        public DataSource evolutionDataSource() {
            JndiDataSourceLookup dataSourceLookup = new JndiDataSourceLookup();
            return dataSourceLookup.getDataSource(oracleDS1);
        }

        @Bean(name="dataSource2", destroyMethod = "")
        @Profile("dev")
        @Primary
        public DataSource orbisQueryOnlyDataSource() {
            JndiDataSourceLookup dataSourceLookup = new JndiDataSourceLookup();
            return dataSourceLookup.getDataSource(oracleDS2);
        }

        @Bean(name="dataSource3", destroyMethod = "")
        @Profile("dev")

        public DataSource orbisExportDataSource() {
            JndiDataSourceLookup dataSourceLookup = new JndiDataSourceLookup();
            return dataSourceLookup.getDataSource(oracleDS3);
        }
    }

TomcatEmbeddedServletContainerFactory

@Bean
    public TomcatEmbeddedServletContainerFactory tomcatFactory() {
        return new TomcatEmbeddedServletContainerFactory() {

            @Override
            protected TomcatEmbeddedServletContainer getTomcatEmbeddedServletContainer(Tomcat tomcat) {
                tomcat.enableNaming();
                return super.getTomcatEmbeddedServletContainer(tomcat);
            }

            @Override
            protected void postProcessContext(Context context) {
                ContextResource oracleDS1JNDIResource = new ContextResource();
                oracleDS1JNDIResource.setName("jdbc/oracleDS1");
                oracleDS1JNDIResource.setType(DataSource.class.getName());
                oracleDS1JNDIResource.setProperty("driverClassName", "oracle.jdbc.driver.OracleDriver");
                oracleDS1JNDIResource.setProperty("url", "jdbc:oracle:thin:@localhost:1521/mydbservice1");
                oracleDS1JNDIResource.setProperty("username", "db-user-name");
                oracleDS1JNDIResource.setProperty("password", "db-user-pass");
                oracleDS1JNDIResource.setProperty("factory", "org.apache.tomcat.jdbc.pool.DataSourceFactory");
                context.getNamingResources().addResource(oracleDS1JNDIResource);

                ContextResource oracleDS2JNDIResource = new ContextResource();
                oracleDS2JNDIResource.setName("jdbc/oracleDS2");
                oracleDS2JNDIResource.setType(DataSource.class.getName());
                oracleDS2JNDIResource.setProperty("driverClassName", "oracle.jdbc.driver.OracleDriver");
                oracleDS2JNDIResource.setProperty("url", "jdbc:oracle:thin:@localhost:1521/mydbservice2");
                oracleDS2JNDIResource.setProperty("username", "db-user-name");
                oracleDS2JNDIResource.setProperty("password", "db-user-pass");
                oracleDS2JNDIResource.setProperty("factory", "org.apache.tomcat.jdbc.pool.DataSourceFactory");
                context.getNamingResources().addResource(oracleDS2JNDIResource);

                ContextResource oracleDS3JNDIResource = new ContextResource();
                oracleDS3JNDIResource.setName("jdbc/oracleDS3");
                oracleDS3JNDIResource.setType(DataSource.class.getName());
                oracleDS3JNDIResource.setProperty("driverClassName", "oracle.jdbc.driver.OracleDriver");
                oracleDS3JNDIResource.setProperty("url", "jdbc:oracle:thin:@localhost:1521/mydbservice3");
                oracleDS3JNDIResource.setProperty("username", "db-user-name");
                oracleDS3JNDIResource.setProperty("password", "db-user-pass");
                oracleDS3JNDIResource.setProperty("factory", "org.apache.tomcat.jdbc.pool.DataSourceFactory");
                context.getNamingResources().addResource(oracleDS3JNDIResource);                

            }
        };
    }

但是当我运行这个Spring启动应用程序时,它会抛出异常。你能帮我解决一下我在这里失踪的事吗?我尝试将@Primary添加到所有DataSource bean中。但没有运气。

org.springframework.beans.factory.NoUniqueBeanDefinitionException:没有'javax.sql.DataSource'类型的限定bean可用:期望的单个匹配bean但找到3:dataSource1,dataSource2,dataSource3

Caused by: org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type 'javax.sql.DataSource' available: expected single matching bean but found 3: dataSource1,dataSource2,dataSource3
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveNamedBean(DefaultListableBeanFactory.java:1041) ~[spring-beans-4.3.13.RELEASE.jar:4.3.13.RELEASE]
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBean(DefaultListableBeanFactory.java:345) ~[spring-beans-4.3.13.RELEASE.jar:4.3.13.RELEASE]
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBean(DefaultListableBeanFactory.java:340) ~[spring-beans-4.3.13.RELEASE.jar:4.3.13.RELEASE]
    at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1092) ~[spring-context-4.3.13.RELEASE.jar:4.3.13.RELEASE]
    at org.springframework.boot.autoconfigure.jdbc.DataSourceInitializer.init(DataSourceInitializer.java:77) ~[spring-boot-autoconfigure-1.5.9.RELEASE.jar:1.5.9.RELEASE]
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_112]
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_112]
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_112]
    at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_112]
    at org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor$LifecycleElement.invoke(InitDestroyAnnotationBeanPostProcessor.java:366) ~[spring-beans-4.3.13.RELEASE.jar:4.3.13.RELEASE]
    at org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor$LifecycleMetadata.invokeInitMethods(InitDestroyAnnotationBeanPostProcessor.java:311) ~[spring-beans-4.3.13.RELEASE.jar:4.3.13.RELEASE]
    at org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor.postProcessBeforeInitialization(InitDestroyAnnotationBeanPostProcessor.java:134) ~[spring-beans-4.3.13.RELEASE.jar:4.3.13.RELEASE]
    ... 38 common frames omitted
spring-boot datasource jndi embedded-tomcat-8
2个回答
0
投票

应该至少有一个名为dataSource的bean。因此要么将任何一个现有的bean替换为dataSource1的exp dataSource,要么创建一个新的bean。

试着说,改变

@Bean(name="dataSource1", destroyMethod = "")
@Profile("dev")
@Primary
public DataSource evolutionDataSource() {
     JndiDataSourceLookup dataSourceLookup = new JndiDataSourceLookup();
            return dataSourceLookup.getDataSource(oracleDS1);
}

@Bean(name="dataSource", destroyMethod = "")
@Profile("dev")
@Primary
public DataSource evolutionDataSource() {
    JndiDataSourceLookup dataSourceLookup = new JndiDataSourceLookup();
            return dataSourceLookup.getDataSource(oracleDS1);
}

要么 只需从任何现有的@Primary咖啡豆中移除dataSource*。在同一个@Primary下,最多1个豆可以有@Profile


0
投票

我能够解决这个问题。问题是,我在Spring启动应用程序中定义了所有数据源,并且还导入了依赖的spring上下文文件。这意味着,我也将相同的数据源配置到我导入的spring上下文文件中。我从OracleDataSourceConfiguration中删除了所有数据源bean(如我在上面的问题中所述),并使用TomcatEmbeddedServletContainerFactory初始化JNDI数据源(引用this),其名称与我导入的spring上下文文件中提到的名称相同。它对我有用。

 <jee:jndi-lookup id="dataSource" jndi-name="jdbc/myDataSource" />
© www.soinside.com 2019 - 2024. All rights reserved.