Search code examples
javaspringmybatisspring-annotations

Spring 4, MyBatis, multiple data sources with annotations


I am currently in a Spring 4 application that uses MyBatis and is completely annotation-driven (that cannot change per architecture requirements). I am trying to add a second data source definition with a completely separate set of mapping configurations.

The problem I am having is that I cannot get the two data sources to play nicely together.

I created a new, virtually identical class and added @Qualifier data to the new file.

The configuration for the classes looks like this:

Data Source 1

@Configuration
@MapperScan (basePackages = "com.myproject.package1", annotationClass = Mapper.class)
public class DataSource1 {

  @Bean
  @Qualifier ("DS1")
  public DataSource getDataSource() {
    /* configuration loaded */
  }

  @Bean
  @Qualifier ("DS1")
  public SqlSessionFactory getSqlSessionFactory() {
    SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
    bean.setDataSource(getDataSource());
    /* mapper resources added */
    return bean.getObject();
  }
}

Data Source 2

@Configuration
@MapperScan (basePackages = "com.myproject.package2", annotationClass = Mapper.class)
public class DataSource2 {

  @Bean
  @Qualifier ("DS2")
  public DataSource getDataSource() {
    /* configuration loaded */
  }

  @Bean
  @Qualifier ("DS2")
  public SqlSessionFactory getSqlSessionFactory() {
    SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
    bean.setDataSource(getDataSource());
    /* mapper resources added */
    return bean.getObject();
  }
}

When this runs I get exception messages like:

org.apache.ibatis.binding.BindingException: Invalid bound statement (not found)

If I comment-out the data in DS2, DS1 works just fine again. I tried adding the mapper scanning configuration data in another bean and setting the name of the SqlSessionFactoryBean to pass into it but that did not work.

Suggestions?

UPDATE

I looked at this post and updated to use the following.

@Bean (name = "the_factory_1")
public SqlSessionFactory getSqlSessionFactory() { /* same code */ }

@Bean
public MapperScannerConfigurer getMapperScannerConfigurer() {
  MapperScannerConfigurer configurer = new MapperScannerConfigurer();
  configurer.setBasePackage("com.myproject.package1");
  configurer.setAnnotationClass(Mapper.class);
  configurer.setSqlSessionFactoryBeanName("the_factory_1");
  return configurer;
}

However, that leads me to this error:

No qualifying bean of type [com.myproject.package1.mapper.MyMapper] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {}

When I debug only one @Bean for the factory gets invoked.

UPDATE 2

If I move everything to a single file all is fine. However, that is not ideal as I want the DataSource definitions to be separated. That's my only hurdle right now.


Solution

  • Please use DAOFactory pattern to get connections for multiple datasources like DS1 and DS2 and use DAOUtil class to provide required configuration using annotation