SoFunction
Updated on 2025-03-09

Springboot2+mybatis implements multi-data configuration methods

The complexity of the business system has increased. In order to solve the database I/O bottleneck, it is natural to disassemble the database, table and split services to deal with it. This will lead to multiple databases that may be accessed in a system and multiple data sources need to be configured.

The first scenario: the project service retrieves basic data from other databases for business processing, so there will be no retables between each database.

The second scenario: In order to reduce the pressure of writing, read and write to the library, read and leave the library and write to the main library. This type of table name and other information are consistent.

The third scenario: Both of the above are available. For some businesses, it is hoped that the summary statistics of large data volumes will not affect the normal business, and the database must be followed by the database (the table information is consistent). Some configuration information does not have read and write pressure, and there will be no database separation (the table information is inconsistent)

Project source code:

/zzsong/

There are three directories:

one:
Directly use multi-@Bean configuration, @MapperScan to distinguish the reading library

two:
Use annotations to identify dataSource, AOP intercepts and injects dynamic data sources

third:
Use spring's Bean naming strategy to distinguish data sources

Project technical selection: springBoot2.2.5 + mybatis + druid + mysql

Look at the main pom package first

<parent>
    <groupId></groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.2.</version>
    <relativePath/> 
  </parent>

        <dependency>
      <groupId></groupId>
      <artifactId>spring-boot-starter-data-jdbc</artifactId>
    </dependency>
    <dependency>
      <groupId></groupId>
      <artifactId>spring-boot-starter-data-jdbc</artifactId>
    </dependency>
    <dependency>
      <groupId></groupId>
      <artifactId>spring-boot-starter-aop</artifactId>
    </dependency>
    <dependency>
      <groupId></groupId>
      <artifactId>mybatis-spring-boot-starter</artifactId>
      <version>2.1.2</version>
    </dependency>

    <dependency>
      <groupId>mysql</groupId>
      <artifactId>mysql-connector-java</artifactId>
      <version>8.0.19</version>
    </dependency>
    <dependency>
      <groupId></groupId>
      <artifactId>druid-spring-boot-starter</artifactId>
      <version>1.1.21</version>
    </dependency>

spring:
 datasource:
  druid:
   core:
    url: jdbc:mysql:///kc_core?characterEncoding=utf-8&serverTimezone=Asia/Shanghai
    username: root
    password: 123456
    driver-class-name: 
    type: 
   schedule:
    url: jdbc:mysql:///kc_schedule?characterEncoding=utf-8&serverTimezone=Asia/Shanghai
    username: root
    password: 123456
    driver-class-name: 
    type: 

The new version of mysql must have serverTimezone, otherwise a connection exception will be reported.

The first type: Scan the relevant data sources through @MapperScans

@Configuration
@MapperScans({
    @MapperScan(basePackages = "", sqlSessionTemplateRef = "coreSqlSessionTemplate",sqlSessionFactoryRef = "coreSqlSessionFactory"),
    @MapperScan(basePackages = "", sqlSessionTemplateRef = "scheduleSqlSessionTemplate",sqlSessionFactoryRef = "scheduleSqlSessionFactory")
})
public class MybatisOneConfig {

  @Bean
  @ConfigurationProperties(prefix = "")
  public DataSource coreDataSource(){
    return ().build();
  }

  @Bean
  public SqlSessionFactory coreSqlSessionFactory(@Qualifier("coreDataSource") DataSource coreDataSource) throws Exception {
    SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean();
    (coreDataSource);
    ().getConfiguration().setJdbcTypeForNull(null);
    ().getConfiguration().setMapUnderscoreToCamelCase(true);
    return ();
  }

  @Bean
  public SqlSessionTemplate coreSqlSessionTemplate(@Qualifier("coreSqlSessionFactory") SqlSessionFactory sqlSessionFactory) throws Exception {
    return new SqlSessionTemplate(sqlSessionFactory);
  }

  //======schedule========
  @Bean
  @ConfigurationProperties(prefix = "")
  public DataSource scheduleDataSource(){
    return ().build();
  }

  @Bean
  public SqlSessionFactory scheduleSqlSessionFactory(@Qualifier("scheduleDataSource") DataSource coreDataSource) throws Exception {
    SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean();
    (coreDataSource);
    ().getConfiguration().setJdbcTypeForNull(null);
    ().getConfiguration().setMapUnderscoreToCamelCase(true);
    return ();
  }

  @Bean
  public SqlSessionTemplate scheduleSqlSessionTemplate(@Qualifier("scheduleSqlSessionFactory") SqlSessionFactory sqlSessionFactory) throws Exception {
    return new SqlSessionTemplate(sqlSessionFactory);
  }
}

The second is the dynamic data source mode, which guides the use of data source through AOP cutting annotation. Use custom annotation @interface to identify the corresponding data source.

Note: The methods in the class call the method with data source and cannot be cut into by AOP.

@Target({, })
@Retention()
@Documented
public @interface TargetDataSource {
  String value();
}

extends spring dynamic DataSource route to match

public class DynamicDataSource extends AbstractRoutingDataSource {

  @Override
  protected Object determineCurrentLookupKey() {
    return ();
  }
}
@Configuration
//@EnableConfigurationProperties()//Don't use this public configuration, Configuration will destroy the configuration of the relevant dataSource@MapperScan("")
public class MybatisConfig {

  @Bean
  @ConfigurationProperties(prefix = "")
  public DataSource coreDataSource() {
    return ().build();
  }

  @Bean
  @ConfigurationProperties(prefix = "")
  public DataSource scheduleDataSource() {
    return ().build();
  }

  @Autowired
  @Qualifier("coreDataSource")
  private DataSource coreDataSource;

  @Autowired
  @Qualifier("scheduleDataSource")
  private DataSource scheduleDataSource;

  @Bean
  public DynamicDataSource dataSource() {
    Map&lt;Object, Object&gt; targetDataSources = new HashMap&lt;&gt;();
    (DataSourceConstants.CORE_DATA_SOURCE, coreDataSource);
    (DataSourceConstants.SCHEDULE_DATA_SOURCE, scheduleDataSource);

    DynamicDataSource dataSource = new DynamicDataSource();

    //Set the data source mapping    (targetDataSources);
///// Set the default data source, and the default data source will be used when it cannot be mapped to the data source    (coreDataSource);
    ();
    return dataSource;
  }
  /**
    * Create SqlSessionFactory based on the data source
    */
  @Bean
  public SqlSessionFactory sqlSessionFactory(DynamicDataSource dataSource) throws Exception {
    SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean();
    (dataSource);
    ().getConfiguration().setJdbcTypeForNull(null);
    ().getConfiguration().setMapUnderscoreToCamelCase(true);
    return ();
  }

  @Bean
  public SqlSessionTemplate sqlSessionTemplate(SqlSessionFactory sqlSessionFactory) throws Exception {
    return new SqlSessionTemplate(sqlSessionFactory);
  }

The third type is to customize the bean naming strategy, and automatically match the data source according to beanName.

@Component
public class CoreBeanNameGenerator implements BeanNameGenerator {
  @Override
  public String generateBeanName(BeanDefinition definition, BeanDefinitionRegistry registry) {
    return "core"+ (());
  }
}

@Component
public class ScheduleBeanNameGenerator implements BeanNameGenerator {
  @Override
  public String generateBeanName(BeanDefinition definition, BeanDefinitionRegistry registry) {
    return "schedule"+ (());
  }
}

Use mybatis MapperScannerConfigurer to automatically scan, inject Mapper interface generation into spring

  @Bean
  public MapperScannerConfigurer coreMapperScannerConfig(CoreBeanNameGenerator coreBeanNameGenerator){
    MapperScannerConfigurer configurer = new MapperScannerConfigurer();
    (coreBeanNameGenerator);
    (",");
    ("coreSqlSessionFactory");
    ("coreSqlSessionTemplate");
    return configurer;
  }

  @Bean
  public MapperScannerConfigurer scheduleMapperScannerConfig(ScheduleBeanNameGenerator scheduleBeanNameGenerator){
    MapperScannerConfigurer configurer = new MapperScannerConfigurer();
    (scheduleBeanNameGenerator);
    (",");
    ("scheduleSqlSessionFactory");
    ("scheduleSqlSessionTemplate");
    return configurer;
  }

At this point, the main points of matching three multiple data sources have been introduced, and the github project will be downloaded in detail. The resources/db contains relevant test tables and data scripts.

This is the article about springboot2+mybatis implementing multi-data configuration methods. For more related springboot2+mybatis, please search for my previous articles or continue browsing the related articles below. I hope everyone will support me in the future!