在Spring中使用多个DataSources

时间:2014-08-03 19:39:24

标签: spring jpa

我正在开发一个使用Spring Data JPA的Spring Boot应用程序,需要连接到两个不同的数据库,而且我遇到了一个问题。当应用程序启动时,它会抛出异常,基本上说明它不知道要使用哪个数据源。这是我的配置类的片段。数据库属性(例如,url,用户名,密码)在application.properties文件中定义。

@Configuration
@ComponentScan(basePackages = {"com.test"})
@EnableJpaRepositories(basePackages = {"com.test.jpa.repository"})
@EnableAutoConfiguration
@EnableTransactionManagement
public class AppConfig {

@Bean(name = "dataSource1")
DataSource dataSource1(@Value("${db1.driverClassName}") String db1DriverClassName,  @Value("${db1.url}") String db1Url, @Value("${db1.username}") String db1Username, @Value("${db1.password}") String db1Password) {
    DataSource dataSource = new DataSource();

    dataSource.setDriverClassName(db1DriverClassName);
    dataSource.setUrl(db1Url);
    dataSource.setUsername(db1Username);
    dataSource.setPassword(db1Password);

    return dataSource;
}

@Bean(name = "dataSource2")
DataSource dataSource2(@Value("${db2.driverClassName}") String db2DriverClassName, @Value("${db2.url}") String db2Url, @Value("${db2.username}") String db2Username, @Value("${db2.password}") String db2Password) {
    DataSource dataSource = new DataSource();

    dataSource.setDriverClassName(db2DriverClassName);
    dataSource.setUrl(db2Url);
    dataSource.setUsername(db2Username);
    dataSource.setPassword(db2Password);

    return dataSource;
}

@Bean(name = "jpaVendorAdapter")
HibernateJpaVendorAdapter jpaVendorAdapter() {
    HibernateJpaVendorAdapter jpaVendorAdapter = new HibernateJpaVendorAdapter();

    jpaVendorAdapter.setDatabase(Database.ORACLE);
    jpaVendorAdapter.setShowSql(false);
    jpaVendorAdapter.setDatabasePlatform("org.hibernate.dialect.Oracle10gDialect");

    return jpaVendorAdapter;
}

@Bean(name = "entityManagerFactory")
@Autowired
LocalContainerEntityManagerFactoryBean entityManagerFactory(@Qualifier("dataSource1") DataSource dataSource, HibernateJpaVendorAdapter jpaVendorAdapter) {
    LocalContainerEntityManagerFactoryBean entityManagerFactory = new LocalContainerEntityManagerFactoryBean();

    entityManagerFactory.setDataSource(dataSource);
    entityManagerFactory.setPersistenceXmlLocation("classpath:persistence.xml");
    entityManagerFactory.setPersistenceUnitName("springdatajpa");
    entityManagerFactory.setJpaVendorAdapter(jpaVendorAdapter);

    return entityManagerFactory;
}

@Bean(name = "transactionManager")
JpaTransactionManager transactionManager(LocalContainerEntityManagerFactoryBean entityManagerFactory) {
    JpaTransactionManager transactionManager = new JpaTransactionManager();
    transactionManager.setEntityManagerFactory(entityManagerFactory.getObject());

    return transactionManager;
}

以下是抛出的异常:

Exception in thread "main" org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private javax.sql.DataSource org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration.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: dataSource1,dataSource2
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:292)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1185)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:537)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:475)
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:304)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:228)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:300)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:195)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:703)
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:760)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:482)
at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh(EmbeddedWebApplicationContext.java:120)
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:648)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:311)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:909)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:898)
at com.wth.service.logging.Application.main(Application.java:11)

我的entityManagerFactory方法注释了@Autowired注释,而dataSource参数前面带有@Qualifier("dataSource1")注释,所以这应该有用。我之前在其他Spring应用程序中做过这个并且没有任何问题。这是我第一次遇到这个例外。

有没有人对可能导致此事的原因有任何想法/想法?

谢谢, 克里斯

4 个答案:

答案 0 :(得分:3)

为了实现这一目标,我使用了以下内容:

@SpringBootApplication(exclude = { 
  DataSourceAutoConfiguration.class, 
  HibernateJpaAutoConfiguration.class, 
  JpaRepositoriesAutoConfiguration.class, 
  DataSourceTransactionManagerAutoConfiguration.class})
public class App...

这相当于:

@Configuration
@ComponentScan
@EnableAutoConfiguration(exclude = { 
  DataSourceAutoConfiguration.class, 
  HibernateJpaAutoConfiguration.class,
  JpaRepositoriesAutoConfiguration.class, 
  DataSourceTransactionManagerAutoConfiguration.class})

然后,每个数据源都有一个单独的Configuration类,定义如下:

@Configuration
@EnableJpaRepositories(
  entityManagerFactoryRef="fooEntityManagerFactory", 
  transactionManagerRef="fooTransactionManager")
public class FooConfig {

  public static final String FOO_QUALIFIER = "Foo";

  @Bean @Qualifier(FOO_QUALIFIER)
  public DataSource fooDataSource() { ... }

  @Bean @Qualifier(FOO_QUALIFIER)
  public EntityManagerFactory fooEntityManagerFactory() { ... }

  @Bean @Qualifier(FOO_QUALIFIER)
  public PlatformTransactionManager fooTransactionManager(
    @Qualifier(FOO_QUALIFIER) EntityManagerFactory emf) { ... }
}

答案 1 :(得分:0)

你真的在Spring的DataSourceAutoConfiguration.class中得到了例外。 由于您自己配置数据源,请尝试删除@EnableAutoConfiguration

DataSourceAutoConfiguration查找DataSource类型(没有限定符)

答案 2 :(得分:0)

根据Rafal Borowiec对我的类似帖子here的回复建议修改您的自动配置以排除JPA存储库配置。

@EnableAutoConfiguration(exclude = JpaRepositoriesAutoConfiguration.class)

答案 3 :(得分:0)

只需从您的配置中删除@EnableAutoConfiguration即可!