[Java] SpringBoot+Mybatis realizes multi-data source connection


Preface

During project development, we often encounter situations where we need to connect to multiple databases. Or the case of multiple different databases. This article is about implementing multiple data source connections using the SpringBoot+Mybatis framework. The database uses SQL Server. Hopefully it helped you!


1. Import the required Jar package (pom.xml)

        <!-- Mybatis -->
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>2.1.4</version>
        </dependency>
        <!-- Druid 数据连接池依赖 -->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid-spring-boot-starter</artifactId>
            <version>1.2.11</version>
        </dependency>
        <!--SQL Server-->
        <dependency>
            <groupId>com.microsoft.sqlserver</groupId>
            <artifactId>mssql-jdbc</artifactId>
            <scope>runtime</scope>
        </dependency>
        <!--SpringBoot 添加jdbc支持-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-jdbc</artifactId>
        </dependency>

2. Define constants of two databases

The code is as follows (example):


/**
 * @author 孤巷.
 * @description
 * @date 2022/8/9 15:58
 */
public class DataBaseNameConstant {
    
    

    /**
     * HIS数据库
     */
    public static final String HIS = "his";

    /**
     * 预约挂号数据库
     */
    public static final String APPOINTMENT = "appointment";
}

3. Create dao and mapper folders

(1) Distinguish two data sources in the dao folder directory
Insert image description here
(2) Distinguish two data sources in the mapper folder

Insert image description here

4. Create datasource configuration class

Create a folder datasource and create five new configuration classes in it.
Insert image description here
The specific code is as follows:
(1) DataSource

import java.lang.annotation.*;

/**
 * mybatis自定义注解,用来声明数据源
 *
 * @author wcs
 */
@Target({
    
    ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface DataSource {
    
    
    String value();
}

(2)DataSourceAspect

import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;

/**
 * mybatis切面,用来切换数据源
 *
 * @author wcs
 */
@Aspect
@Component
@Slf4j
public class DataSourceAspect {
    
    

    @Pointcut("execution(* com.example.web.dao.*.*.*(..))")
    public void dataSourcePointCut() {
    
    

    }

    @Before("dataSourcePointCut()")
    public void before(JoinPoint point) {
    
    
        Object target = point.getTarget();
        DataSource dataSource = target.getClass().getInterfaces()[0].getAnnotation(DataSource.class);
        if (dataSource != null) {
    
    
            String key = dataSource.value();
            log.info("当前运行的数据源为 == {}",key);
            DynamicDataSourceHolder.setDataSource(key);
        }
    }
}

(3)DatasourceConfig

import com.alibaba.druid.pool.DruidDataSource;
import com.example.web.constant.DataBaseNameConstant;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;

import javax.sql.DataSource;
import java.util.HashMap;
import java.util.Map;

/**
 * @author wcs
 * @description 多数据源配置
 * @date 2021/3/13 11:44
 */
@Configuration
public class DatasourceConfig {
    
    

    @Bean(name = DataBaseNameConstant.HIS)
    @ConfigurationProperties(prefix = "spring.datasource.druid.his")
    public DataSource hisDruid() {
    
    
        return new DruidDataSource();
    }

    @Bean(name = DataBaseNameConstant.APPOINTMENT)
    @ConfigurationProperties(prefix = "spring.datasource.druid.appointemnt")
    public DataSource appointemntDruid() {
    
    
        return new DruidDataSource();
    }



    @Bean
    @Primary
    public DynamicDataSource dataSource() {
    
    
        Map<String, DataSource> targetDataSources = new HashMap<>(4);
        targetDataSources.put(DataBaseNameConstant.HIS, hisDruid());
        targetDataSources.put(DataBaseNameConstant.APPOINTMENT, appointemntDruid());
        return new DynamicDataSource(targetDataSources.get(DataBaseNameConstant.HIS), targetDataSources);
    }
}

(4)DynamicDataSource

import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;

import javax.sql.DataSource;
import java.util.HashMap;
import java.util.Map;

/**
 * mybatis自定义数据源
 *
 * @author wcs
 */
public class DynamicDataSource extends AbstractRoutingDataSource {
    
    

    public DynamicDataSource(DataSource defaultTargetDataSource, Map<String, DataSource> targetDataSources) {
    
    
        super.setDefaultTargetDataSource(defaultTargetDataSource);
        super.setTargetDataSources(new HashMap<>(targetDataSources));
        super.afterPropertiesSet();
    }

    @Override
    protected Object determineCurrentLookupKey() {
    
    
        return DynamicDataSourceHolder.getDataSouce();
    }

}

(5)DynamicDataSourceHolder

/**
 * mybatis自定义数据源管理器
 *
 * @author wcs
 */
public class DynamicDataSourceHolder {
    
    
    public static final ThreadLocal<String> holder = new ThreadLocal<String>();

    public static void setDataSource(String name) {
    
    
        holder.set(name);
    }

    public static String getDataSouce() {
    
    
        return holder.get();
    }
}

5. Define the application file

提示:本文中还会用到lombok以及Druid,这两个jar包在网上都能找到
(1) Application.yml file content
code is as follows:

#开发环境配置
server:
  port: 9803
spring:
  servlet:
    multipart:
      max-file-size: 10MB
      max-request-size: 10MB
  datasource:
    druid:
      his:
        url:  jdbc:sqlserver://127.0.0.1:1433;databaseName=test;
        driver-class-name: com.microsoft.sqlserver.jdbc.SQLServerDriver
        username: test
        password: test
        initial-size: 5 #初始化时建立物理连接的个数。
        max-active: 20  #最大连接池数量
        min-idle: 5     #最小连接池数量
        max-wait: 3000  #获取连接时最大等待时间,单位毫秒
        pool-prepared-statements: false #是否缓存preparedStatement,也就是PSCache,PSCache对支持游标的数据库性能提升巨大,比如说oracle,在mysql下建议关闭。
        #要启用PSCache,必须配置大于0,当大于0时,poolPreparedStatements自动触发修改为true。在Druid中,不会存在OraclePSCache占用内存过多的问题,可以把这个数值配置大一些,比如说100
        max-open-prepared-statements: 100
        time-between-eviction-runs-millis: 60000 #配置检测可以关闭的空闲连接间隔时间
        min-evictable-idle-time-millis: 300000 # 配置连接在池中的最小生存时间
        max-evictable-idle-time-millis: 400000
        filters: stat,slf4j #监控统计的stat,以及防sql注入的wall
        web-stat-filter:
          enabled: true
        validation-query: SELECT 1
        # StatViewServlet配置,说明请参考Druid Wiki,配置_StatViewServlet配置
        #是否启用StatViewServlet(监控页面)默认值为false(考虑到安全问题默认并未启动,如需启用建议设置密码或白名单以保障安全)
        stat-view-servlet:
          enabled: true       #是否启用StatViewServlet默认值true
          url-pattern: /druid/* #访问路径为/druid时,跳转到StatViewServlet
          reset-enable: true #是否能够重置数据
          login-username: whxx
          login-password: whxx666.
          allow: localhost
        test-on-borrow: false
        test-on-return: false
        test-while-idle: true
        max-pool-prepared-statement-per-connection-size: 20
        filter:
          stat:
            log-slow-sql: true
            slow-sql-millis: 2000
          slf4j:
            enabled: true
            result-set-log-enabled: false
            statement-create-after-log-enabled: false
            statement-close-after-log-enabled: false
            result-set-open-after-log-enabled: false
            result-set-close-after-log-enabled: false
      appointemnt:
        url: jdbc:sqlserver://127.0.0.1:1433;databaseName=test1;
        driver-class-name: com.microsoft.sqlserver.jdbc.SQLServerDriver
        username: test1
        password: test1
        initial-size: 5 #初始化时建立物理连接的个数。
        max-active: 20  #最大连接池数量
        min-idle: 5     #最小连接池数量
        max-wait: 3000  #获取连接时最大等待时间,单位毫秒
        pool-prepared-statements: false #是否缓存preparedStatement,也就是PSCache,PSCache对支持游标的数据库性能提升巨大,比如说oracle,在mysql下建议关闭。
        #要启用PSCache,必须配置大于0,当大于0时,poolPreparedStatements自动触发修改为true。在Druid中,不会存在Oracle下PSCache占用内存过多的问题,可以把这个数值配置大一些,比如说100
        max-open-prepared-statements: 100
        time-between-eviction-runs-millis: 60000 #配置检测可以关闭的空闲连接间隔时间
        min-evictable-idle-time-millis: 300000 # 配置连接在池中的最小生存时间
        max-evictable-idle-time-millis: 400000
        filters: stat,slf4j #监控统计的stat,以及防sql注入的wall
        web-stat-filter:
          enabled: true
        validation-query: SELECT 1
        # StatViewServlet配置,说明请参考Druid Wiki,配置_StatViewServlet配置
        #是否启用StatViewServlet(监控页面)默认值为false(考虑到安全问题默认并未启动,如需启用建议设置密码或白名单以保障安全)
        stat-view-servlet:
          enabled: true       #是否启用StatViewServlet默认值true
          url-pattern: /druid/* #访问路径为/druid时,跳转到StatViewServlet
          reset-enable: true #是否能够重置数据
          login-username: whxx
          login-password: whxx666.
          allow: localhost
        test-on-borrow: false
        test-on-return: false
        test-while-idle: true
        max-pool-prepared-statement-per-connection-size: 20
        filter:
          stat:
            log-slow-sql: true
            slow-sql-millis: 2000
          slf4j:
            enabled: true
            result-set-log-enabled: false
            statement-create-after-log-enabled: false
            statement-close-after-log-enabled: false
            result-set-open-after-log-enabled: false
            result-set-close-after-log-enabled: false
mybatis:
  mapper-locations: classpath:mapper/*/*.xml #xml文件位置
  type-aliases-package: com.example.web.bean
  configuration:
    map-underscore-to-camel-case: true
    call-setters-on-nulls: true #处理数据为null时键值对不存在



Summarize

The code of this post has been posted, and you can ask other questions in the comment area below, and the blogger will provide a reply in time! Thank you for your attention!

Guess you like

Origin blog.csdn.net/qq_42666609/article/details/130221136