SpringBoot is now the back-end framework for many, many corporate applications because it is fast to build and integrate with third parties better and faster. So as the business expanded, the increase of business volume, this time will be involved in depots table, although the word sounds familiar, as a programmer is easy to understand, but I think I should also have a lot of readers never contact depots table, today we don’t talk about how to depots table, but how about SpringBoot integration of multiple data sources. That is how to access different (multiple) databases.


Let’s just start, let’s just create a clean SpringBoot application.

<parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> The < version > 2.1.0. RELEASE < / version > < relativePath / > <! -- lookup parent from repository --> </parent>Copy the code

<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter</artifactId> < version > 1.3.2 < / version > < / dependency > < the dependency > < groupId > mysql < / groupId > <artifactId>mysql-connector-java</artifactId> <scope>runtime</scope> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-jdbc</artifactId> </dependency> <dependency> < the groupId > org. Projectlombok < / groupId > < artifactId > lombok < / artifactId > < version > 1.18.8 < / version > < / dependency >Copy the code

With maven coordinates in place, we can set up the project and configure SpringBoot to integrate two Mysql data sources. First we create two databases test1 and test2 locally and create two tables with the same structure.

CREATE TABLE `user` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'user ID',
  `username` varchar(100) CHARACTER SET utf8 NOT NULL COMMENT 'Username',
  `password` varchar(100) NOT NULL COMMENT 'password',
  `create_time` datetime DEFAULT NULL COMMENT 'Creation time',
  PRIMARY KEY (`id`)
) ENGINE=MyISAM AUTO_INCREMENT=3 DEFAULT CHARSET=latin1;Copy the code

Configure the application.yml file in our project to include the database information

spring:
  datasource:
    test1:
      driver-class-name: com.mysql.cj.jdbc.Driver
      jdbc-url: jdbc:mysql://localhost:3306/test1? useUnicode=true&characterEncoding=utf-8&useSSL=true&serverTimezone=UTC
      username: root
      password: 1234
​
    test2:
      driver-class-name: com.mysql.cj.jdbc.Driver
      jdbc-url: jdbc:mysql://localhost:3306/test2? useUnicode=true&characterEncoding=utf-8&useSSL=true&serverTimezone=UTC
      username: root
      password: 1234Copy the code

The next step is to write our configuration class, which is the most critical part of integrating multiple data sources.

​import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.SqlSessionTemplate;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.jdbc.DataSourceBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
​
import javax.sql.DataSource;
​
/**
 * @ClassName DataSource2Config
 * @Description TODO
 * @Auther lbt
 * @Date 2019/6/28/028 10:07
 * @Version 1.0
 */
@Configuration
@MapperScan(basePackages = "com.example.mapper.test1", sqlSessionFactoryRef = "test1SqlSessionFactory")
public class DataSource1Config {
​
​
    @Bean(name = "test1DataSource")
    @ConfigurationProperties(prefix = "spring.datasource.test1")
    @Primary
    public DataSource test1DataSource() {
        return DataSourceBuilder.create().build();
    }
​
    @Bean(name = "test1SqlSessionFactory")
    @Primary
    public SqlSessionFactory test1SqlSessionFactory(@Qualifier("test1DataSource") DataSource dataSource) throws Exception {
        SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
        bean.setDataSource(dataSource);
        return bean.getObject();
    }
​
    @Bean(name = "test1TransactionManager")
    @Primary
    public DataSourceTransactionManager test1TransactionManager(@Qualifier("test1DataSource") DataSource dataSource) {
        return new DataSourceTransactionManager(dataSource);
    }
​
    @Bean(name = "test1SqlSessionTemplate")
    @Primary
    public SqlSessionTemplate test1SqlSessionTemplate(@Qualifier("test1SqlSessionFactory") SqlSessionFactory sqlSessionFactory) {
        returnnew SqlSessionTemplate(sqlSessionFactory); }}Copy the code

Configuration of the second data source

​import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.SqlSessionTemplate;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.jdbc.DataSourceBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
​
import javax.sql.DataSource;
​
@Configuration
@MapperScan(basePackages = "com.example.mapper.test2", sqlSessionFactoryRef = "test2SqlSessionFactory")
public class DataSource2Config {
​
​
    @Bean(name = "test2DataSource")
    @ConfigurationProperties(prefix = "spring.datasource.test2")
    public DataSource test2DataSource() {
        return DataSourceBuilder.create().build();
    }
​
    @Bean(name = "test2SqlSessionFactory")
    public SqlSessionFactory test2SqlSessionFactory(@Qualifier("test2DataSource") DataSource dataSource) throws Exception {
        SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
        bean.setDataSource(dataSource);
        return bean.getObject();
    }
​
    @Bean(name = "test2TransactionManager")
    public DataSourceTransactionManager test2TransactionManager(@Qualifier("test2DataSource") DataSource dataSource) {
        return new DataSourceTransactionManager(dataSource);
    }
​
    @Bean(name = "test2SqlSessionTemplate")
    public SqlSessionTemplate test2SqlSessionTemplate(@Qualifier("test2SqlSessionFactory") SqlSessionFactory sqlSessionFactory) {
        returnnew SqlSessionTemplate(sqlSessionFactory); }}Copy the code

Now that our configuration is complete, let’s write a Controller class to test whether our integrated data source really works.

@RestController​
​​public class TestController {
​
    @Autowired
    private User1Service user1Service;
​
    @Autowired
    private User2Service user2Service;
​
    @RequestMapping("/user1")
    public Object user1Controller() {
​
        List<UserPo> all = user1Service.findAll();
​
        return all;
    }
​
    @RequestMapping("/user2")
    public Object user2Controller() {
​
        List<UserPo> all = user2Service.findAll();
​
        returnall; }}Copy the code

I wrote two Controller methods that access different interfaces, so let’s look at the results.

When we access user1 we return the following:


When we access user2, we access the following

Although it looks very simple, if you haven’t written it, you will walk a lot of pits. When I first integrated it, I met a lot of pits. In order to help you repeat the pit mining, I shared it for your reference.


Next to share with you, these days in the docking wechat pay, encountered pit, has wechat pay business process.

GitHub address: github.com/liangbintao…