SpringBoot+dynamic-datasource实现多数据源(msyql、sqlserver、postgresql)手动切换

这篇具有很好参考价值的文章主要介绍了SpringBoot+dynamic-datasource实现多数据源(msyql、sqlserver、postgresql)手动切换。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

场景

SpringBoot+MybatisPlus+dynamic-datasources实现连接Postgresql和mysql多数据源:

SpringBoot+MybatisPlus+dynamic-datasources实现连接Postgresql和mysql多数据源-CSDN博客

上面实现通过注解和配置文件的方式去进行多数据源操作。

如果业务需求,比如查询第三方接口时提供的是sqlserver的视图连接方式时,需要在调用

接口时手动新增数据源-检验数据源是否可用-切换当前数据源-查询数据-清除当前数据源

实现以上流程,可以通过mybatisplus的dynamic-datasource来实现。

dynamic-datasource

开源文档付费

基础必读(免费) · dynamic-datasource · 看云

多数据源 | MyBatis-Plus

SpringBoot+dynamic-datasource实现多数据源(msyql、sqlserver、postgresql)手动切换,SpringBoot,spring boot,sqlserver,postgresql

但是可以通过引入依赖后查看其源码以及借助网上一些教程,可以找到源码中需要用到的几个类

SpringBoot+dynamic-datasource实现多数据源(msyql、sqlserver、postgresql)手动切换,SpringBoot,spring boot,sqlserver,postgresql

注:

博客:
霸道流氓气质-CSDN博客

实现

1、引入pom依赖

这里springboot的版本是2.6.13

dynamic-datasource的版本是3.2.1

        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>dynamic-datasource-spring-boot-starter</artifactId>
            <version>3.2.1</version>
        </dependency>

引入msyql、sqlserver、postgresql所需的依赖

        <!--MySQL驱动-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>
        <dependency>
            <groupId>org.postgresql</groupId>
            <artifactId>postgresql</artifactId>
        </dependency>
        <!-- sqlserver-->
        <dependency>
            <groupId>com.microsoft.sqlserver</groupId>
            <artifactId>mssql-jdbc</artifactId>
            <version>7.4.1.jre8</version>
        </dependency>

引入Mybatisplus所需依赖

        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>3.5.1</version>
        </dependency>

引入其他依赖

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>   
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>

2、这里使用默认的HikariCP数据库连接池,没使用Druid,流程一样

参考上面博客已经实现了连接Mysql和sqlserver多数据源

spring:
  datasource:
    dynamic:
      primary: master #设置默认的数据源或者数据源组,默认值即为master
      strict: false #严格匹配数据源,默认false. true未匹配到指定数据源时抛异常,false使用默认数据源
      datasource:
        master:
         url:jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
          username: root
          password: 123456
          driver-class-name: com.mysql.cj.jdbc.Driver
          dbcp2:
            min-idle: 5                                # 数据库连接池的最小维持连接数
            initial-size: 5                            # 初始化连接数
            max-total: 5                               # 最大连接数
            max-wait-millis: 150                       # 等待连接获取的最大超时时间

        pg:
          url: jdbc:postgresql://127.0.0.1:5432/test
          username: postgres
          password: 123456
          driver-class-name: org.postgresql.Driver
          dbcp2:
            min-idle: 5                                # 数据库连接池的最小维持连接数
            initial-size: 5                            # 初始化连接数
            max-total: 5                               # 最大连接数
            max-wait-millis: 150                       # 等待连接获取的最大超时时间

3、SpringBoot+dynamic-datasource使用DynamicRoutingDataSource获取当前所有数据源

代码实现:

@SpringBootTest
class DynamicDataSourceTest {

    @Autowired
    private DataSource dataSource;


    /**
     * 获取当前所有数据源
     */
    @Test
    void getAllDataSource() {
        DynamicRoutingDataSource ds = (DynamicRoutingDataSource) dataSource;
        System.out.println(ds.getCurrentDataSources().keySet());
    }
}

其中DataSource是javax.sql包下的。

javax.sql.DataSource 是 jdk 提供的接口,各个连接池厂商 和 Spring 都对 DataSource 进行了设计和实现。

javax.sql.DataSource 是连接到物理数据源的工厂接口。它是 java.sql.DriverManager 功能的替代者,

是获取数据库连接的首选方法。

DataSource 数据源在必要时可以修改它的属性。例如,如果将数据源移动到其他服务器,

则可以更改 DataSource 的属性,这样访问该数据源的代码不需要做任何更改就可以获取到达到目的。

单元测试运行结果:

SpringBoot+dynamic-datasource实现多数据源(msyql、sqlserver、postgresql)手动切换,SpringBoot,spring boot,sqlserver,postgresql

4、SpringBoot+DynamicRoutingDataSources实现添加与删除数据源

这里通过代码将sqlserver的数据源添加到DynamicRoutingDataSource中

这就需要用到creator包下的各种创建器

SpringBoot+dynamic-datasource实现多数据源(msyql、sqlserver、postgresql)手动切换,SpringBoot,spring boot,sqlserver,postgresql

这里是默认HikariCP的连接池,所以使用该创建器,如果是其它类型则使用对应的创建器。

数据源创建需要的参数这里新建一个DTO类用来赋值

import lombok.Builder;
import lombok.Data;

@Data
@Builder
public class DataSourceDTO {
    private String dataSourceName;
    private String driverClassName;
    private String url;
    private String username;
    private String password;
}

编写单元测试

@SpringBootTest
class DynamicDataSourceTest {

    @Autowired
    private DataSource dataSource;

    @Autowired(required = false)
    private HikariDataSourceCreator hikariDataSourceCreator;

    /**
     * 获取当前所有数据源
     */
    @Test
    void getAllDataSource() {
        DynamicRoutingDataSource ds = (DynamicRoutingDataSource) dataSource;
        System.out.println(ds.getCurrentDataSources().keySet());
    }

    /**
     * 添加 与 删除 HikariCP数据源
     */
    @Test
    void addHcpDataSource() {
        DataSourceDTO sqlserver = DataSourceDTO.builder()
                .dataSourceName("sqlserver")
                .driverClassName("com.microsoft.sqlserver.jdbc.SQLServerDriver")
                .url("jdbc:sqlserver://127.0.0.1:1433;DatabaseName=test")
                .username("sa")
                .password("123456")
                .build();
        DataSourceProperty dataSourceProperty = new DataSourceProperty();
        BeanUtils.copyProperties(sqlserver,dataSourceProperty);
        DataSource sqlserverDataSource = hikariDataSourceCreator.createDataSource(dataSourceProperty);
        DynamicRoutingDataSource ds = (DynamicRoutingDataSource) dataSource;
        ds.addDataSource(sqlserver.getDataSourceName(),sqlserverDataSource);
        System.out.println(ds.getCurrentDataSources().keySet());
        ds.removeDataSource(sqlserver.getDataSourceName());
        System.out.println(ds.getCurrentDataSources().keySet());
    }
}

单元测试运行结果:

SpringBoot+dynamic-datasource实现多数据源(msyql、sqlserver、postgresql)手动切换,SpringBoot,spring boot,sqlserver,postgresql

5、SpringBoot中+HikariCP实现检测数据源是否可用

预实现手动切换当前数据源,首先需要确保配置的数据源的相关参数可以正常连接可用

新建检测数据源的方法

    /**
     *  检测数据源
     * @param dataSourceDTO
     * @return
     */

    private boolean checkDataBase(DataSourceDTO dataSourceDTO){
        Connection connection = null;
        try {
            DataSource dataSource = creatHcpDataSource(dataSourceDTO);
            connection = dataSource.getConnection();
            Statement statement = connection.createStatement();
            statement.execute("select * from s_user");
            return true;
        } catch (Exception exception) {
            return false;
        }finally {
            try {
                if(null!=connection){
                    connection.close();
                }
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }
        }
    }

这其中就是创建数据源并进行连接和执行sql,确保无异常发生则代表连接可用,这里执行的sql以及表名

均写死,其中s_user是sqlserver中新建的表。

用到创建数据源的方法creatHcpDataSource的实现

    /**
     * 创建Hcp datasource
     * @param dataSourceDTO
     * @return
     */
    private DataSource creatHcpDataSource(DataSourceDTO dataSourceDTO){
        HikariDataSource dataSource = new HikariDataSource();
        //控制客户端(即用户程序)等待池中连接的最长毫秒数。如果在没有连接可用的情况下超过此时间,则将抛出SQLException异常。最低可以接受的连接超时为250毫秒。默认值:3000(30秒)。这是一个很重要的问题排查指标
        dataSource.setConnectionTimeout(3000l);
        //HikariCP将尝试仅基于jdbcUrl通过DriverManager解析驱动程序,但对于某些较旧的驱动程序必须指定driverClassName。除非用户收到明显的错误消息,表明未找到驱动程序,否则可忽略此属性。默认值:无
        //dataSource.setDataSourceClassName(dataSourceDTO.getDriverClassName());
        dataSource.setJdbcUrl(dataSourceDTO.getUrl());
        dataSource.setUsername(dataSourceDTO.getUsername());
        dataSource.setPassword(dataSourceDTO.getPassword());
        //表示连接池的用户定义名称,主要显示在日志记录和JMX管理控制台中,以标识池和池配置。该属性的默认值:自动生成
        dataSource.setPoolName(dataSourceDTO.getDataSourceName());
        return dataSource;
    }

相关参数和配置自行搜索和设置,这里重点关注

dataSource.setConnectionTimeout(3000l);

设置超时时间3秒。

控制客户端(即用户程序)等待池中连接的最长毫秒数。如果在没有连接可用的情况下超过此时间,则将抛出SQLException异常。

最低可以接受的连接超时为250毫秒。默认值:3000(30秒)。这是一个很重要的问题排查指标

dataSource.setPoolName

示连接池的用户定义名称,主要显示在日志记录和JMX管理控制台中,以标识池和池配置。该属性的默认值:自动生成

编写单元测试:

    /**
     * 检测数据源
     */
    @Test
    void testDataSource(){
        DataSourceDTO sqlserver = DataSourceDTO.builder()
                .dataSourceName("sqlserver")
                .driverClassName("com.microsoft.sqlserver.jdbc.SQLServerDriver")
                .url("jdbc:sqlserver://127.0.0.1:1433;DatabaseName=test")
                .username("sa")
                .password("123456")
                .build();
        boolean checkDataBase = checkDataBase(sqlserver);
        System.out.println(checkDataBase);
        DataSourceDTO sqlserverWrong = DataSourceDTO.builder()
                .dataSourceName("sqlserver")
                .driverClassName("com.microsoft.sqlserver.jdbc.SQLServerDriver")
                .url("jdbc:sqlserver://192.168.1.2:1433;DatabaseName=test")
                .username("sa")
                .password("123456")
                .build();
        boolean checkDataBaseWrong = checkDataBase(sqlserverWrong);
        System.out.println(checkDataBaseWrong);
    }

第二个故意写了一个不存在的数据源的地址

运行单元测试:

SpringBoot+dynamic-datasource实现多数据源(msyql、sqlserver、postgresql)手动切换,SpringBoot,spring boot,sqlserver,postgresql

6、SpringBoot+DynamicDataSourceContextHolder实现手动切换清除当前数据源

动态数据源切换的关键在于DynamicDataSourceContextHolder类,它提供了一种机制来存储当前使用的数据源。

它主要由两部分组成,一部分是线程本地的数据源容器,另一部分是管理动态数据源的数据源切换类。

查看其源码

SpringBoot+dynamic-datasource实现多数据源(msyql、sqlserver、postgresql)手动切换,SpringBoot,spring boot,sqlserver,postgresql

主要用到的方法

push 设置当前线程数据源 如非必要不要手动调用,调用后确保最终清除

poll 清空当前线程数据源 如果当前线程是连续切换数据源 只会移除掉当前线程的数据源名称

clear 强制清空本地线程  防止内存泄漏,如手动调用了push可调用此方法确保清除

编写单元测试:

    /**
     * 手动切换数据源
     */
    @Test
    void changeDataSource() {
        DataSourceDTO sqlserver = DataSourceDTO.builder()
                .dataSourceName("sqlserver")
                .driverClassName("com.microsoft.sqlserver.jdbc.SQLServerDriver")
                .url("jdbc:sqlserver://127.0.0.1:1433;DatabaseName=test")
                .username("sa")
                .password("123456")
                .build();
        boolean checkDataBase = checkDataBase(sqlserver);
        if(checkDataBase){
            DataSourceProperty dataSourceProperty = new DataSourceProperty();
            BeanUtils.copyProperties(sqlserver,dataSourceProperty);
            DataSource sqlserverDataSource = hikariDataSourceCreator.createDataSource(dataSourceProperty);
            DynamicRoutingDataSource ds = (DynamicRoutingDataSource) dataSource;
            Set<String> dataSourceSet = ds.getCurrentDataSources().keySet();
            if (!dataSourceSet.contains(sqlserver.getDataSourceName())) {
                ds.addDataSource(sqlserver.getDataSourceName(),sqlserverDataSource);
            }
            //push 设置当前线程数据源 如非必要不要手动调用,调用后确保最终清除
            DynamicDataSourceContextHolder.push(sqlserver.getDataSourceName());
            List<SUser> sUsers = sUserMapper.selectList(new LambdaQueryWrapper<>());
            System.out.println(sUsers);
            //DynamicDataSourceContextHolder.poll();
            //poll 清空当前线程数据源 如果当前线程是连续切换数据源 只会移除掉当前线程的数据源名称
            //clear 强制清空本地线程  防止内存泄漏,如手动调用了push可调用此方法确保清除
            DynamicDataSourceContextHolder.clear();
            ds.removeDataSource(sqlserver.getDataSourceName());
        }else {
            System.out.println("数据源连接异常");
        }
    }

这里一定要对数据源可用性进行校验,确保可用才进行数据源添加和切换当前数据源操作

其中SUser是Sqlserver中新建表对应的实体类

import com.baomidou.mybatisplus.annotation.TableName;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;

@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
@TableName(value = "s_user")
public class SUser implements Serializable {

    private static final long serialVersionUID = -5514139686858156155L;

    private Integer id;

    private String name;

    private Integer age;

    private String address;

}

调用查询的mapper接口实现

import com.badao.demo.entity.SUser;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.springframework.stereotype.Repository;

@Repository
public interface SUserMapper extends BaseMapper<SUser> {

}

单元测试运行结果

SpringBoot+dynamic-datasource实现多数据源(msyql、sqlserver、postgresql)手动切换,SpringBoot,spring boot,sqlserver,postgresql

7、将以上手动切换数据源和执行业务逻辑的操作封装成工具类

import com.baomidou.dynamic.datasource.toolkit.DynamicDataSourceContextHolder;
import java.util.function.Supplier;

/**
 * 数据源切换工具类
 */
public class DynamicDSExecute {

    public static <T> T execute(String dsName, Supplier<T> executor){
        try {
            DynamicDataSourceContextHolder.push(dsName);
            return executor.get();
        }finally {
            DynamicDataSourceContextHolder.clear();
        }
    }
}

这里用到了函数式接口,可参考如下

java8中常用函数式接口Supplier<T>、Consumer<T>、Function<T,R>、Predicate<T>使用示例:

java8中常用函数式接口Supplier<T>、Consumer<T>、Function<T,R>、Predicate<T>使用示例_java8 函数式编程supplier接口案例大全-CSDN博客

然后调用工具类时文章来源地址https://www.toymoban.com/news/detail-808228.html

            Supplier<List<SUser>> supplier = () -> sUserMapper.selectList(new LambdaQueryWrapper<>());
            List<SUser> sUsers = DynamicDSExecute.execute(sqlserver.getDataSourceName(),supplier);

到了这里,关于SpringBoot+dynamic-datasource实现多数据源(msyql、sqlserver、postgresql)手动切换的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Springboot+mybatis-plus+dynamic-datasource+Druid 多数据源 分布式事务

    背景 处理多数据源事务一直是一个复杂而棘手的问题,通常我们有两种主流的解决方法。 第一种是通过Atomikos手动创建多数据源事务,这种方法更适合数据源数量较少,参数配置不复杂,对性能要求不高的项目。然而,这种方法的最大困难在于需要手动配置大量设置,这可能

    2024年02月11日
    浏览(40)
  • 【源码解析】多数据源 dynamic-datasource快速入门及源码解析

    启动的时候,会加载在 dynamic-datasource-spring-boot-starter 的jar包中的 spring.factories 在 DynamicDataSourceAutoConfiguration 会注入 DynamicRoutingDataSource DynamicRoutingDataSource#afterPropertiesSet ,系统启动的时候会加载所有的数据源 在 DynamicDataSourceAutoConfiguration 会注入 DynamicDataSourceProvider AbstractData

    2023年04月21日
    浏览(60)
  • Springboot+dynamic-datasource+Druid数据库配置加密

    Springboot+mybatis-plus+dynamic-datasource+Druid数据库配置加密 背景 生产环境中, 为了保密,我们希望将数据库密码加密, 甚至用户名和jdbc连接串加密。本章我们使用由苞米豆(baomidou)团队开发的 dynamic-datasource 多数据源组件自带的加密工具实现数据库配置加密 从 dynamic-datasource-star

    2024年02月04日
    浏览(43)
  • Dynamic DataSource 多数据源配置【 Springboot + DataSource + MyBatis Plus + Druid】

    MybatisPlus多数据源配置主要解决的是多数据库连接和切换的问题。在一些大型应用中,由于数据量的增长或者业务模块的增多,可能需要访问多个数据库。这时,就需要配置多个数据源。 2.1.1、引用依赖 2.1.2、application.yml 配置 2.1.3、通用配置类 2.1.4、使用方式 这里便不过多的

    2024年02月03日
    浏览(48)
  • dynamic-datasource can not find primary datasource

    动态数据源找不到主数据源 可能导入多数据源依赖导致 把依赖注释 运行成功

    2024年02月08日
    浏览(45)
  • dynamic-datasource Please check the setting of primary解决方案

    报这个错的原因是数据库使用多数据源没有指定主数据源导致的错误。  解决方法如图所示,通过配置指定dynamic的primary指定主数据库的配置 切记箭头两处的名称一样

    2024年02月13日
    浏览(55)
  • spring boot mybatis-plus dynamic-datasource 配置文件 相关依赖环境配置

    spring boot mybatis-plus dynamic-datasource 配置文件 相关依赖环境配置 ##yaml配置 ##父级pom.xml配置 ##子模块pom.xml配置 ##表结构 ##Test.java ##TestMapper.xml ##TestMapper.java ##TestService.java ##TestController ##项目启动类BootStrap.java ##浏览器访问 192.168.3.188:8866/yym/test/v1/test

    2024年02月02日
    浏览(44)
  • MyBatis Plus 插件 动态数据源实现原理与源码讲解 (dynamic-datasource-spring-boot-starter-master)

    目录 1. 介绍 2. 基本原理 3. 源码介绍 3.1 使用 AOP 拦截,方法执行前获取到当前方法要用的数据源 3.2 实现自定义 DataSource 接口,实现 DataSource 接口的 getConnect 方法做动态处理 多数据源即一个项目中同时存在多个不同的数据库连接池。 比如 127.0.0.1:3306/test   127.0.0.1:3307/test 

    2024年02月07日
    浏览(44)
  • 使用多数据源dynamic-datasource-spring-boot-starter遇到的问题记录

    记录使用多数据源dynamic-datasource-spring-boot-starter遇到的问题: 1、工程启动失败 缺少clickhouse连接驱动,引入对应的maven依赖 2、clickhouse的sql语句读到了mysql数据库 在工程的配置文件只配置了ck数据源配置的时候,@DS(“数据源名称”)用在service接口上没什么问题。 由于新的需求

    2024年02月15日
    浏览(56)
  • 分享一个优秀的动态数据源开源库-dynamic-datasource-spring-boot-starter

    在我们的Java后端研发工作中, 有时候由于业务的快速迭代和数据的安全隔离性,往往会为不同的 API业务线分配不同的数据库,即一个微服务经常需要和多个数据源打交道。 dynamic-datasource-spring-boot-starter 是一个基于springboot的快速集成多数据源的启动器。 其支持 Jdk 1.7+, Spring

    2024年02月12日
    浏览(59)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包