preface

Welcome to our GitHub repository Star: github.com/bin39232820… The best time to plant a tree was ten years ago, followed by now. I know many people don’t play QQ anymore, but for a moment of nostalgia, welcome to join the six-vein Shenjian Java rookie learning group, group chat number: 549684836 encourage everyone to write blog on the road of technology

omg

Why did Xiao66 write this article? Equivalent of a record, we just have a business, because to do the report, but, if is real-time report query, request time but timeout, then one of our solution is, we need when they need statistical data with timing task put in storage, but is this database for them to read and write, but? In order to not see all the libraries on the academic affairs side, so we need to use two databases in a project, then we have to implement multiple data sources, so there is a record of this article.

I have been in charge of this system for a long time. I would like to make fun of the reason. The system I am now in charge of is a system that has been iterated by many people, and then adopts a hierarchical structure. And then what? The configuration of each service database is placed in the API or admin project, so if I want to change, I can only add multiple data sources in the project to be changed. For example, if I want to add data sources in admin, I can only add data sources in admin, not in API, so now there is a problem. Then our multi-data source solution is about two ways, one is subcontracting, the other is we use Spring’s dynamic configuration interface, if we adopt the second way, then we need to do in the DAO section (every time we go to the DAO section), and then how do I use admin things dao, Because the CONTROLLER relies on the DAO, it cannot be said that I rely on the controller in the DAO, that is not interdependent, so another solution is to rewrite a module to rely on the DAO, but this is also not possible, because it affects the API (API has its own database configuration, Dao also have would be repeated load, the API is also dependent on the dao), cause the configuration API will also have change, so it want to can only adopt the way of the subcontract to expand the, write so much, just want to express an architecture design of the expanding is really very important, if a project after five personal hand can do his taste the same, So these guys are pretty good. I always think that a product is alive, and so is the code, and if the code of a product ends up being unscalable, then the project becomes more and more difficult to iterate, and good architectural design is still very important. Let’s take a look at Spring’s configuration of multiple data sources

Code integration

Package structure

Step 1: Add dependencies

<? xml version="1.0" encoding="UTF-8"? > <project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> < modelVersion > 4.0.0 < / modelVersion > < groupId > com. Wangbin < / groupId > < artifactId > springboot - moresource < / artifactId > <version>1.0.0-SNAPSHOT</version> <packaging>jar</packaging> <description>SpringBoot configure multiple data sources </description> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> < version > 2.0.4. RELEASE < / version > < / parent > < properties > <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> < project. Reporting. OutputEncoding > utf-8 < / project. Reporting. OutputEncoding > < Java version > 1.8 < / Java version > < druid version > 1.1.2 < / druid version > < the mysql - version > 5.1.21 < / mysql - the version > < mybatis - plus version > 2.1.8 < / mybatis - plus. Version > < mybatisplus - spring - the boot - starter. Version > 1.0.5 < / mybatisplus - spring - the boot - starter. Version > < / properties > < dependencies > <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-aop</artifactId> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>${mysql-connector.version}</version> <scope>runtime</scope> </dependency> <dependency> <groupId>com.louislivi.fastdep</groupId> < artifactId > fastdep - a datasource < / artifactId > < version > 1.0.3 < / version > < / dependency > < the dependency > <groupId>com.alibaba</groupId> <artifactId>druid</artifactId> <version>${druid.version}</version> </dependency> <! <dependency> <groupId>com.baomidou</groupId> <artifactId> MyBatis -plus</artifactId> <version>${mybatis-plus.version}</version>
        </dependency>
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatisplus-spring-boot-starter</artifactId>
            <version>${mybatisplus-spring-boot-starter.version}</version>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope> </dependency> <dependency> <groupId>org.hamcrest</groupId> <artifactId>hamcrest-all</artifactId> < version > 1.3 < / version > < scope >test</scope> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.mybatis.spring.boot</groupId> < artifactId > mybatis - spring - the boot - starter < / artifactId > < version > 2.0.0 < / version > < / dependency > < the dependency > < the groupId > com. Alibaba < / groupId > < artifactId > druid - spring - the boot - starter < / artifactId > < version > 1.1.10 < / version > </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.28</version> <scope> Runtime </scope> </dependency> </dependencies> <build> <plugins> <plugin> . < groupId > org, apache maven plugins < / groupId > < artifactId > maven - compiler - plugin < / artifactId > < version > 3.6.1 < / version > <configuration> <! --<proc>none</proc>--> <source> 1.8 < /source> <target>1.8</target> </configuration> </plugin> <plugin> <groupId>org.apache.maven.plugins</groupId> < artifactId > maven - surefire plugin < / artifactId > < version > 2.20 < / version > < configuration > < the skip >true</skip> </configuration> </plugin> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> <executions> </executions> </plugin> </plugins> <resources> <resource>  <directory>src/main/resources</directory> </resource> <resource> <directory>src/main/java</directory> <includes> <include>**/*.xml</include> </includes> </resource> </resources> </build> </project>Copy the code

Modifying properties file

spring.datasource.one.url=jdbc:mysql:/pos? serverTimezone=UTC&useSSL=false&autoReconnect=true&tinyInt1isBit=false&useUnicode=true&characterEncoding=utf8 spring.datasource.one.username=root spring.datasource.one.password=admin@123 spring.datasource.one.type=com.alibaba.druid.pool.DruidDataSource spring.datasource.two.url=jdbc:mysql:/biz? serverTimezone=UTC&useSSL=false&autoReconnect=true&tinyInt1isBit=false&useUnicode=true&characterEncoding=utf8
spring.datasource.two.username=root
spring.datasource.two.password=admin@123
spring.datasource.two.type=com.alibaba.druid.pool.DruidDataSource

Copy the code

A configuration file with multiple data sources is fine

Entity class

package com.wangbin.entity; import com.baomidou.mybatisplus.activerecord.Model; import com.baomidou.mybatisplus.annotations.TableId; import com.baomidou.mybatisplus.annotations.TableName; import com.baomidou.mybatisplus.enums.IdType; import java.io.Serializable; import java.util.Date; Public class User extends Model<User> {private} public class User extends Model<User> {private static final long serialVersionUID = 1L; /** * primary key ID */ @tableId (value="id".type= IdType.AUTO) private Integer id; /** * username */ private String username; /** * name */ private String name; /** * password */ private String password; /** * private String salt; /** * private String phone; /** * Note */ private String tips; /** * Status 1: normal 2: disabled */ private Integer state; /** * private Date createdTime; /** * private Date updatedTime; /** * get primary key ID. ** @returnPrimary key ID. */ public IntegergetId() {
        returnid; ** @param ID Primary key ID. */ public voidsetId(Integer id) { this.id = id; } /** ** get the account. ** @returnAccount. */ public StringgetUsername() {
        returnusername; } /** * set the username. ** @param usernamesetUsername(String username) { this.username = username; } /** * get the name. ** @returnName. */ public StringgetName() {
        returnname; } /** * set the name. ** @param name namesetName(String name) { this.name = name; } /** * get the password. ** @returnPassword */ public StringgetPassword() {
        returnpassword; } /** * set the password. ** @param password Set the passwordsetPassword(String password) { this.password = password; } /** * get md5 password salt. ** @returnMd5 Password salt. */ public StringgetSalt() {
        returnsalt; } /** * set md5 password salt ** @param salt MD5 password salt */ public voidsetSalt(String salt) { this.salt = salt; } /** * obtain the contact number. ** @returnContact number. */ public StringgetPhone() {
        returnphone; } /** * set contact number ** @param phone Contact number */ public voidsetPhone(String phone) { this.phone = phone; } /** * Obtain the remarks. ** @return*/ public StringgetTips() {
        returntips; } /** * set remarks. ** @param tips RemarkssetTips(String tips) { this.tips = tips; } /** * Obtain status 1: normal 2: disabled ** @returnStatus 1: normal 2: disabled */ public IntegergetState() {
        returnstate; } /** * Set status 1: normal 2: disabled ** @param state State 1: normal 2: disabled */ public voidsetState(Integer state) { this.state = state; } /** * get the creation time. ** @return*/ public DategetCreatedTime() {
        returncreatedTime; ** @param createdTime Creates time. */ public void creates timesetCreatedTime(Date createdTime) { this.createdTime = createdTime; } /** * get the update time. ** @return*/ public DategetUpdatedTime() {
        returnupdatedTime; } /** @param updatedTime Specifies the update timesetUpdatedTime(Date updatedTime) {
        this.updatedTime = updatedTime;
    }

    @Override
    protected Serializable pkVal() {
        returnthis.id; }}Copy the code

config

This is the key, configuring the data sources under different packages

DataSourceConfig

package com.wangbin.config;

import com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceBuilder;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import javax.sql.DataSource;

/**
 * @author 小六六
 * @version 1.0
 * @date 2020/4/24 21:34
 */
@Configuration
public class DataSourceConfig {
    @Bean
    @ConfigurationProperties(prefix = "spring.datasource.one")
    DataSource dsOne() {
        return DruidDataSourceBuilder.create().build();
    }
    @Bean
    @ConfigurationProperties(prefix = "spring.datasource.two")
    DataSource dsTwo() {
        returnDruidDataSourceBuilder.create().build(); }}Copy the code

MyBatisConfigOne

package com.wangbin.config; 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.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import javax.annotation.Resource; import javax.sql.DataSource; /** * @author small 66 * @version 1.0 * @date 2020/4/24 21:35 */ @configuration @mapperscan (basePackages ="com.wangbin.mybatis.mapper1",sqlSessionFactoryRef = "sqlSessionFactory1",sqlSessionTemplateRef = "sqlSessionTemplate1")
public class MyBatisConfigOne {
    @Resource(name = "dsOne")
    DataSource dsOne;

    @Bean
    SqlSessionFactory sqlSessionFactory1() {
        SqlSessionFactory sessionFactory = null;
        try {
            SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
            bean.setDataSource(dsOne);
            sessionFactory = bean.getObject();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return sessionFactory;
    }
    @Bean
    SqlSessionTemplate sqlSessionTemplate1() {
        returnnew SqlSessionTemplate(sqlSessionFactory1()); }}Copy the code

MyBatisConfigTwo

package com.wangbin.config; 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.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import javax.annotation.Resource; import javax.sql.DataSource; /** * @author small 66 * @version 1.0 * @date 2020/4/24 21:36 */ @configuration @mapperscan (basePackages ="com.wangbin.mybatis.mapper2",sqlSessionFactoryRef = "sqlSessionFactory2",sqlSessionTemplateRef = "sqlSessionTemplate2")
public class MyBatisConfigTwo {
    @Resource(name = "dsTwo")
    DataSource dsTwo;

    @Bean
    SqlSessionFactory sqlSessionFactory2() {
        SqlSessionFactory sessionFactory = null;
        try {
            SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
            bean.setDataSource(dsTwo);
            sessionFactory = bean.getObject();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return sessionFactory;
    }
    @Bean
    SqlSessionTemplate sqlSessionTemplate2() {
        returnnew SqlSessionTemplate(sqlSessionFactory2()); }}Copy the code

Mapper

UserMapperOne

package com.wangbin.mybatis.mapper1; import com.wangbin.entity.User; import org.apache.ibatis.annotations.Mapper; import java.util.List; /** * @author 小 606 * @date 2020/4/24 21:37 */ @mapper public interface UserMapperOne {List<User> getAllUser(); }Copy the code

UserMapperOne.xml

<? xml version="1.0" encoding="UTF-8"? > <! DOCTYPE mapper PUBLIC"- / / mybatis.org//DTD Mapper / 3.0 / EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.wangbin.mybatis.mapper1.UserMapperOne">
    <select id="getAllUser" resultType="com.wangbin.entity.User">
        select * from t_user;
    </select>
</mapper>

Copy the code

UserMapper

package com.wangbin.mybatis.mapper2; import com.wangbin.entity.User; import java.util.List; Public interface UserMapper {List<User> getAllUser(); public interface UserMapper {List<User> getAllUser(); }Copy the code

UserMapper.xml

<? xml version="1.0" encoding="UTF-8"? > <! DOCTYPE mapper PUBLIC"- / / mybatis.org//DTD Mapper / 3.0 / EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.wangbin.mybatis.mapper2.UserMapper">
    <select id="getAllUser" resultType="com.wangbin.entity.User">
        select * from t_user;
    </select>
</mapper>

Copy the code

The test class

SpringTest

import com.wangbin.Application; import com.wangbin.entity.User; import com.wangbin.mybatis.mapper1.UserMapperOne; import com.wangbin.mybatis.mapper2.UserMapper; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.context.junit4.SpringRunner; import java.util.List; /** * @author 小 606 * @date 2020/4/24 20:59 */ @springboottest (classes ={application.class}) @RunWith(SpringRunner.class) public class SpringTest { @Autowired private UserMapper userMapper; @Autowired private UserMapperOne userMapperOne; @Test public voidTest1() {
        List<User> allUser = userMapper.getAllUser();
        for (User user : allUser) {
            System.out.println(user.getName());
        }
        List<User> allUser1 = userMapperOne.getAllUser();
        for(User user : allUser1) { System.out.println(user.getName()); }}}Copy the code

The results of

At the end

It’s pretty simple, isn’t it? Subcontracting is able to achieve, write this article, is a note, if it is helpful to the reader is also very good.

Daily for praise

Ok, everybody, that’s all for this article, you can see people here, they are real fans.

Creation is not easy, your support and recognition, is the biggest motivation for my creation, we will see in the next article

Six pulse excalibur | article “original” if there are any errors in this blog, please give criticisms, be obliged!