12

I am using Spring Java Based configuration for configure multiple database with Spring Data. In the configuration file, i am creating two data source for MySQL and MSSQL-Server. When trying to inject dependency to the entity manager using @Resource annotation i am getting following exception:

org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type [javax.sql.DataSource] is defined: expected single matching bean but found 2: mysql_datasource,secure_datasource at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1016) at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:904) at org.springframework.beans.factory.support.ConstructorResolver.resolveAutowiredArgument(ConstructorResolver.java:815) at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:743) 

Following is my Code:

@Bean(name="secure_datasource") public DataSource dataSource(){ try{ ComboPooledDataSource dataSource = new ComboPooledDataSource(); dataSource.setJdbcUrl(environment.getProperty("sc.db.url")); dataSource.setDriverClass(environment.getProperty("sc.db.driver.class")); dataSource.setUser(environment.getProperty("sc.db.username")); dataSource.setPassword(environment.getProperty("sc.db.password")); dataSource.setIdleConnectionTestPeriod(60); dataSource.setMaxPoolSize(10); dataSource.setMaxStatements(7); dataSource.setMinPoolSize(1); return dataSource; }catch(Exception ex){ throw new RuntimeException(ex); } } ................. @Bean(name="mysql_datasource") public DataSource dataSource(){ try{ ComboPooledDataSource dataSource = new ComboPooledDataSource(); dataSource.setJdbcUrl(environment.getProperty("db.url")); dataSource.setDriverClass(environment.getProperty("db.driver.class")); dataSource.setUser(environment.getProperty("db.username")); dataSource.setPassword(environment.getProperty("db.password")); dataSource.setIdleConnectionTestPeriod(60); dataSource.setMaxPoolSize(100); dataSource.setMaxStatements(50); dataSource.setMinPoolSize(10); return dataSource; }catch(Exception ex){ throw new RuntimeException(ex); } } ....... @Resource(value="mysql_datasource") @Bean(name="entity_manager_factory") public LocalContainerEntityManagerFactoryBean entityManagerFactory(DataSource dataSource){ LocalContainerEntityManagerFactoryBean factoryBean = new LocalContainerEntityManagerFactoryBean(); factoryBean.setDataSource(dataSource); factoryBean.setPersistenceProviderClass(HibernatePersistenceProvider.class); factoryBean.setPackagesToScan(environment.getProperty("package.scan")); factoryBean.setJpaVendorAdapter(jpaVendorAdapter); return factoryBean; } 

I am also trying to use @Qualifier annotation as suggest i this link, but still getting error. Using 2 beans of the same type: javax.sql.DataSource in Spring

3 Answers 3

10

I had the same problem and after a lot of headache I stumbled upon this doc that made me feel really dumb :(

All you need is @Primary on one of your DataSources and Spring-Boot won't get confused anymore... Here is one of my configurations... The rest are pretty much identical, pointing to other DBs and with no @Primary on them...

@Configuration @EnableTransactionManagement @EntityScan(basePackages = {"somepackage.entities"}) @EnableJpaRepositories(entityManagerFactoryRef = "emfDB1", transactionManagerRef = "tmDB1", basePackages = {"somepackage.repositories"}) class PersistenceDB1 { @Bean @Primary DataSource dsDB1() { BasicDataSource dataSource = new BasicDataSource(); dataSource.setUrl("jdbc:mysql://someserver:3306/proativo"); dataSource.setUsername("username"); dataSource.setPassword("password"); dataSource.setDriverClassName("com.mysql.jdbc.Driver"); return dataSource; } @Bean @Primary LocalContainerEntityManagerFactoryBean emfDB1() { LocalContainerEntityManagerFactoryBean entityManagerFactoryBean = new LocalContainerEntityManagerFactoryBean(); entityManagerFactoryBean.setDataSource(dsDB1()); entityManagerFactoryBean.setJpaVendorAdapter(new EclipseLinkJpaVendorAdapter()); entityManagerFactoryBean.setPersistenceXmlLocation("classpath:META-INF/DB1-persistence.xml"); Properties jpaProperties = new Properties(); jpaProperties.put("eclipselink.weaving", "false"); jpaProperties.put("eclipselink.logging.level", "SEVERE"); // SEVERE / FINEST entityManagerFactoryBean.setJpaProperties(jpaProperties); return entityManagerFactoryBean; } @Bean @Primary JpaTransactionManager tmDB1() { JpaTransactionManager transactionManager = new JpaTransactionManager(); transactionManager.setEntityManagerFactory(emfDB1().getNativeEntityManagerFactory()); return transactionManager; } } 

Edit: Forgot to mention: Probably due to the way my configuration classes are done, the method of excluding some classes on @EnableAutoConfiguration didn't work for me...

Sign up to request clarification or add additional context in comments.

2 Comments

I added the @Primary directive but when I make the transaction manager, both of their session factories use the primary datasource. Is there a way to specifically tell the sessionfactory to use which datasource?
We probably need a bit of your code to figure out since, as you can see in the above code, the session manager is specified on the transaction manager creation.
7

I my case, the configuration was on a xml file, so I only have to add the primary="true" to the bean tag of one of the defined datasources.

Comments

5

I had the same problem and found this old post that explained it:

http://xantorohara.blogspot.ch/2013/11/spring-boot-jdbc-with-multiple.html

It looks like if you need multiple data sources, the Spring Boot magic runs out, and you have to take over the configuration manually.

In my case, I had to modify the EnableAutoConfiguration to take over the data source and transaction manager configuration myself:

@EnableAutoConfiguration(exclude = {DataSourceAutoConfiguration.class,DataSourceTransactionManagerAutoConfiguration.class}) 

It looks like the Spring Boot magic ran out at the point I had to use multiple data sources...

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.