I've been using Spring with MyBatis and it's been working really well for a single database. I ran into difficulties when trying to add another database (see reproducible example on Github).
I'm using Spring Java configuration (i.e. not XML). Most of the examples I've seen show how to achieve this using XML.
I have two data configuration classes (A & B) like this:
@Configuration
@MapperScan("io.woolford.database.mapper")
public class DataConfigDatabaseA {
@Bean(name="dataSourceA")
public DataSource dataSourceA() throws SQLException {
SimpleDriverDataSource dataSource = new SimpleDriverDataSource();
dataSource.setDriver(new com.mysql.jdbc.Driver());
dataSource.setUrl("jdbc:mysql://" + dbHostA + "/" + dbDatabaseA);
dataSource.setUsername(dbUserA);
dataSource.setPassword(dbPasswordA);
return dataSource;
}
@Bean
public SqlSessionFactory sqlSessionFactory() throws Exception {
SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean();
sessionFactory.setDataSource(dataSourceA());
return sessionFactory.getObject();
}
}
Two mappers, and a service that autowires the mappers:
@Service
public class DbService {
@Autowired
private DbMapperA dbMapperA;
@Autowired
private DbMapperB dbMapperB;
public List<Record> getDabaseARecords(){
return dbMapperA.getDatabaseARecords();
}
public List<Record> getDabaseBRecords(){
return dbMapperB.getDatabaseBRecords();
}
}
The application won't start:
Error creating bean with name 'dataSourceInitializer':
Invocation of init method failed; 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: dataSourceB,dataSourceA
I've read that it's possible to use the @Qualifier
annotation to disambiguate the autowiring, though I wasn't sure where to add it.
Can you see where I'm going wrong?
@Qaulifier("name_of_bean")
can be placed before or after the@Autowired
annotation of the particular field you want to target I believe – Violetavioletta@Qualifier("dataSourceA")
and the expected bean error changed: "expected single matching bean but found 2: sqlSessionFactoryA,sqlSessionFactoryB". I believe it's only possible to add one qualifier to@Autowired
, so perhaps I need to add a name to@Component
and use that as a qualifier? – Schuman@Primary
to the DataSource and SqlSessionFactory beans in the DataConfigDatabaseA class and it magically started working! However, it doesn't work when@Primary
is added to DataConfigDatabaseB instead. This is okay as a workaround, though I don't think it's a good rule-of-thumb because there doesn't seem to be a rule to determine which beans should be annotated with@Primary
. – Schuman@Bean public DataSourceInitializer dataSourceInitializer(final DataSource dataSource) { final DataSourceInitializer initializer = new DataSourceInitializer(); initializer.setDataSource(dataSource); return initializer; }
It didn't work. I need to learn more about Spring to understand what's happening. – Schuman