使用 2 个相同类型的 bean:Spring 中的 javax.sql.DataSource

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/23687369/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-14 00:41:56  来源:igfitidea点击:

Using 2 beans of the same type: javax.sql.DataSource in Spring

javaspring

提问by DilTeam

I am developing a Spring Boot based application in which I would like to create 2 beans: One will point to 'Oracle' database; the other will point to Hive. I've declared them as follows:

我正在开发一个基于 Spring Boot 的应用程序,我想在其中创建 2 个 bean:一个指向“Oracle”数据库;另一个将指向 Hive。我已将它们声明如下:

public @Bean
BoneCPDataSource metadataDataSource() {
    BoneCPDataSource boneCPDataSource = new BoneCPDataSource();
    boneCPDataSource.setDriverClass(getDriver());
    boneCPDataSource.setJdbcUrl(getJdbcUrl());
    boneCPDataSource.setUser(getUser());
    boneCPDataSource.setPassword(getPassword());
    boneCPDataSource.setMaxConnectionsPerPartition(5);
    boneCPDataSource.setPartitionCount(5);
    return boneCPDataSource;
}

public @Bean
BasicDataSource hiveDataSource() {
    BasicDataSource basicDataSource = new BasicDataSource();

    // Note: In a separate command window, use port forwarding like this:
    //
    // ssh -L 127.0.0.1:9996:<server>:<port> -l <userid> <server>
    //
    // and then login as the generic user.

    basicDataSource.setDriverClassName("org.apache.hadoop.hive.jdbc.HiveDriver");
    basicDataSource.setUrl("jdbc:hive://127.0.0.1:9996:10000/mytable");
    return basicDataSource;
}

Problem is at the startup I am getting this:

问题是在启动时我得到了这个:

Exception in thread "main"
org.springframework.beans.factory.BeanCreationException: Error
creating bean with name
'org.springframework.boot.actuate.autoconfigure.EndpointAutoConfiguration':
Injection of autowired dependencies failed; nested exception is
org.springframework.beans.factory.BeanCreationException: Could not
autowire field: private javax.sql.DataSource
org.springframework.boot.actuate.autoconfigure.EndpointAutoConfiguration.dataSource;
nested exception is
org.springframework.beans.factory.NoUniqueBeanDefinitionException: No
qualifying bean of type [javax.sql.DataSource] is defined: expected
single matching bean but found 2: metadataDataSource,hiveDataSource

Mainly because both of them inherit from javax.sql.DataSource. What's the best way to fix this?

主要是因为它们都继承自javax.sql.DataSource。解决这个问题的最佳方法是什么?



EDIT:

编辑:

Now I've declared them as follows:

现在我已将它们声明如下:

public @Bean (name="metadataDataSource")
BoneCPDataSource metadataDataSource() {
    BoneCPDataSource boneCPDataSource = new BoneCPDataSource();
    boneCPDataSource.setDriverClass(getDriver());
    boneCPDataSource.setJdbcUrl(getJdbcUrl());
    boneCPDataSource.setUser(getUser());
    boneCPDataSource.setPassword(getPassword());
    boneCPDataSource.setMaxConnectionsPerPartition(5);
    boneCPDataSource.setPartitionCount(5);
    return boneCPDataSource;
}

public @Bean (name="hiveDataSource")
BasicDataSource hiveDataSource() {
    BasicDataSource basicDataSource = new BasicDataSource();

    // Note: In a separate command window, use port forwarding like this:
    //
    // ssh -L 127.0.0.1:9996:<server>:<port> -l <userid> <server>
    //
    // and then login as the generic user.

    basicDataSource.setDriverClassName("org.apache.hadoop.hive.jdbc.HiveDriver");
    basicDataSource.setUrl("jdbc:hive://127.0.0.1:9996:10000/mytable");
    return basicDataSource;
}

And got this exception:

并得到了这个例外:

Exception in thread "main"
org.springframework.beans.factory.BeanCreationException: Error
creating bean with name
'org.springframework.boot.actuate.autoconfigure.EndpointAutoConfiguration':
Injection of autowired dependencies failed; nested exception is
org.springframework.beans.factory.BeanCreationException: Could not
autowire field: private javax.sql.DataSource
org.springframework.boot.actuate.autoconfigure.EndpointAutoConfiguration.dataSource;
nested exception is
org.springframework.beans.factory.NoUniqueBeanDefinitionException: No
qualifying bean of type [javax.sql.DataSource] is defined: expected
single matching bean but found 2: metadataDataSource,hiveDataSource

The other classes are referring to these beans as follows:

其他类引用这些 bean 如下:

public class MetadataProcessorImpl implements MetadataProcessor {

公共类 MetadataProcessorImpl 实现 MetadataProcessor {

@Autowired
@Qualifier("metadataDataSource")
BoneCPDataSource metadataDataSource;

@Controller public class HiveController {

@Controller 公共类 HiveController {

@Autowired
@Qualifier("hiveDataSource")
BasicDataSource hiveDataSource;

采纳答案by Luiggi Mendoza

Give different names to your beans when using @Bean:

使用时为您的 bean 赋予不同的名称@Bean

@Bean(name="bonecpDS")
public BoneCPDataSource metadataDataSource() {
    //...
}

@Bean(name="hiveDS")
public BasicDataSource hiveDataSource() {
    //...
}

Then, when injecting the bean, use @Qualifierand specify the name of the bean:

然后,在注入 bean 时,使用@Qualifier并指定 bean 的名称:

@Component
public class FooComponent {
    @Autowired
    @Qualifier("bonecpDS")
    DataSource boneCPDataSource;
}

回答by Danilo

Set one of the beam as @Primary as described in the section 67.2 Configure Two DataSources

如第67.2配置两个数据源中所述,将光束之一设置为 @Primary

http://docs.spring.io/spring-boot/docs/current-SNAPSHOT/reference/htmlsingle/#howto-two-datasources

http://docs.spring.io/spring-boot/docs/current-SNAPSHOT/reference/htmlsingle/#howto-two-datasources

回答by Tina Zhang

If you want to use two data sources at the same time and they are not primary and secondary, you should disable DataSourceAutoConfigurationon your application annotated by @SpringBootApplication(excludes = {DataSourceAutoConfiguration.class}).

如果您想同时使用两个数据源并且它们不是主要的和次要的,您应该DataSourceAutoConfiguration在由@SpringBootApplication(excludes = {DataSourceAutoConfiguration.class}).

Since the DataSourceAutoConfigurationwill init the DataSourceInitializerclass. The init method in DataSourceInitializerclass needs to get DataSource. When there is more than one DataSource, the system gets confused by getting which DataSource.

由于DataSourceAutoConfiguration将初始化DataSourceInitializer该类。类中的 init 方法DataSourceInitializer需要获取DataSource. 当有多个时DataSource,系统会因获取 which 而感到困惑DataSource

@SpringBootApplication(excludes = {DataSourceAutoConfiguration.class})means that system won't load the DataSourceAutoConfiguration.classwhen run the application.

@SpringBootApplication(excludes = {DataSourceAutoConfiguration.class})意味着系统不会DataSourceAutoConfiguration.class在运行应用程序时加载。

回答by Mahesh Vemula

I faced similar issue. Added @SpringBootApplication(exclude = {DataSourceAutoConfiguration.class,DataSourceTransactionManagerAutoConfiguration.class})

我遇到了类似的问题。添加@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class,DataSourceTransactionManagerAutoConfiguration.class})

and added manual configuration. It worked!

并添加了手动配置。有效!