在 Spring 中使用多个数据源
Posted
技术标签:
【中文标题】在 Spring 中使用多个数据源【英文标题】:Using Multiple DataSources With Spring 【发布时间】:2014-09-26 07:39:52 【问题描述】:我正在开发一个使用 Spring Data JPA 的 Spring Boot 应用程序,并且需要连接到两个不同的数据库,但我遇到了一个问题。当应用程序启动时,它抛出一个异常,基本上说明它不知道要使用哪个数据源。这是我的配置类的 sn-p。数据库属性(例如 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 应用程序中做过这个并且没有任何问题。这是我第一次遇到这个异常。
是否有人对可能导致此问题的原因有任何想法/想法?
谢谢, 克里斯
【问题讨论】:
尝试删除@EnableAutoConfiguration。看起来您正在自己配置 bean。你得到的例外是在 Spring 类中,看起来不像在你的类中。 【参考方案1】:为了让这个工作,我使用了以下内容:
@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
@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) ...
【讨论】:
【参考方案2】:您确实在 Spring 的 DataSourceAutoConfiguration.class
中遇到了异常。
由于您是自己配置数据源,请尝试删除 @EnableAutoConfiguration
DataSourceAutoConfiguration
查找类型 DataSource(不带限定符)
【讨论】:
【参考方案3】:正如 Rafal Borowiec 在回复我的类似帖子 here 所建议的那样,修改您的自动配置以排除 JPA 存储库配置。
@EnableAutoConfiguration(exclude = JpaRepositoriesAutoConfiguration.class)
【讨论】:
【参考方案4】:只需从您的配置中删除 @EnableAutoConfiguration!
【讨论】:
以上是关于在 Spring 中使用多个数据源的主要内容,如果未能解决你的问题,请参考以下文章
在春季批处理(spring-boot-1.5.2.RELEASE)中使用多个数据源在启动时引发异常