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

时间:2014-05-15 19:47:44

标签: java spring

我正在开发一个基于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;
}

问题是在创业时我得到了这个:

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

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


编辑:

现在我已按照以下方式宣布:

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;
}

得到了这个例外:

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

其他类引用这些bean如下:

公共类MetadataProcessorImpl实现MetadataProcessor {

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

@Controller 公共类HiveController {

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

4 个答案:

答案 0 :(得分:17)

将其中一个光束设置为@Primary 如 67.2配置两个数据源

一节中所述

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

答案 1 :(得分:11)

使用@Bean时为您的bean指定不同的名称:

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

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

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

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

答案 2 :(得分:0)

如果要同时使用两个数据源,而它们不是主要数据和次要数据,则应在由DataSourceAutoConfiguration注释的应用程序上禁用@SpringBootApplication(excludes = {DataSourceAutoConfiguration.class})

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

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

答案 3 :(得分:0)

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

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