苞米豆的多数据源 → dynamic-datasource-spring-boot-starter,挺香的!

这篇具有很好参考价值的文章主要介绍了苞米豆的多数据源 → dynamic-datasource-spring-boot-starter,挺香的!。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

开心一刻

  2023年元旦,我妈又开始了对我的念叨

  妈:你到底想多少岁结婚

  我:60

  妈:60,你想找个多大的

  我:找个55的啊,她55我60,结婚都有退休金,不用上班不用生孩子,不用买车买房,成天就是玩儿

  我:而且一结婚就是白头偕老,多好

  我妈直接一大嘴巴子呼我脸上

苞米豆的多数据源 → dynamic-datasource-spring-boot-starter,挺香的!

需求背景

  最近接到一个需求,需要从两个数据源获取数据,然后进行汇总展示

  一个数据源是 MySQL ,另一个数据源是 SQL Server 

  楼主是一点都不慌的,因为我写过好几篇关于数据源的文章

    spring集成mybatis实现mysql读写分离

    原理解密 → Spring AOP 实现动态数据源(读写分离),底层原理是什么

    Spring 下,关于动态数据源的事务问题的探讨

  我会慌?

苞米豆的多数据源 → dynamic-datasource-spring-boot-starter,挺香的!

  但还是有点小拒绝,为什么了?

  自己实现的话,要写的东西还是很多,要写 AOP ,还要实现 AbstractRoutingDataSource ,还要用到 ThreadLocal ,...

  如果考虑更远一些,事务、数据源之间的嵌套等等,要如何保证正确?

  但好在这次需求只是查询,然后汇总,问题就简单很多了,但还是觉得有点小繁琐

苞米豆的多数据源 → dynamic-datasource-spring-boot-starter,挺香的!

  当然,如上只是楼主的臆想

  有小伙伴可能会问道:能不能合到一个数据源?

  楼主只能说:别问了,再问就不礼貌了

苞米豆的多数据源 → dynamic-datasource-spring-boot-starter,挺香的!

  既然改变不了,那就盘它

苞米豆的多数据源 → dynamic-datasource-spring-boot-starter,挺香的!

  难道就没有现成的多数据源工具?

  因为用到了 Mybatis-Plus ,楼主试着 Google 了一下

苞米豆的多数据源 → dynamic-datasource-spring-boot-starter,挺香的!

  直接一发入魂,眼前一黑,不对,是眼前一亮!

  感觉就是它了!

MyBatis-Plus 多数据源

  关于苞米豆(baomidou),我们最熟悉的肯定是 MyBatis-Plus 

  但旗下还有很多其他优秀的组件

苞米豆的多数据源 → dynamic-datasource-spring-boot-starter,挺香的!

  多数据源就是其中一个,今天我们就来会会它

  数据源准备

  用 docker 准备一个 MySQL 和 SQL Server ,图省事,两个数据库服务器放到同个 docker 下了

  有小伙伴会觉得放一起不合适,有单点问题!

  楼主只是为了演示,纠结那么细,当心敲你狗头

苞米豆的多数据源 → dynamic-datasource-spring-boot-starter,挺香的!

   MySQL 版本: 8.0.27 

苞米豆的多数据源 → dynamic-datasource-spring-boot-starter,挺香的!

  建库: datasource_mysql ,建表: tbl_user ,并插入初始化数据

苞米豆的多数据源 → dynamic-datasource-spring-boot-starter,挺香的!苞米豆的多数据源 → dynamic-datasource-spring-boot-starter,挺香的!
CREATE DATABASE datasource_mysql;
USE datasource_mysql;
CREATE TABLE tbl_user (
    id INT UNSIGNED NOT NULL AUTO_INCREMENT,
    user_name VARCHAR(50),
    PRIMARY KEY(id)
);
INSERT INTO tbl_user(user_name) VALUES('张三'),('李四');
View Code

苞米豆的多数据源 → dynamic-datasource-spring-boot-starter,挺香的!

   SQL Server 版本: Microsoft SQL Server 2017 ... ,是真长,跟楼主一样长!

苞米豆的多数据源 → dynamic-datasource-spring-boot-starter,挺香的!

  建库: datasource_mssql ,建表: tbl_order ,并插入初始化数据

苞米豆的多数据源 → dynamic-datasource-spring-boot-starter,挺香的!苞米豆的多数据源 → dynamic-datasource-spring-boot-starter,挺香的!
CREATE DATABASE datasource_mssql;
USE datasource_mssql;
CREATE TABLE tbl_order(
    id BIGINT PRIMARY KEY IDENTITY(1,1),
    order_no NVARCHAR(50),
    created_at DATETIME NOT NULL DEFAULT(GETDATE()),
    updated_at DATETIME NOT NULL DEFAULT(GETDATE())
);
INSERT INTO tbl_order(order_no) VALUES('123456'),('654321');
View Code

苞米豆的多数据源 → dynamic-datasource-spring-boot-starter,挺香的!

  dynamic-datasource 使用

  基于 spring-boot 2.2.10.RELEASE 、 mybatis-plus 3.1.1 搭建

   dynamic-datasource-spring-boot-starter 也是 3.1.1 

  依赖很简单, pom.xml 

苞米豆的多数据源 → dynamic-datasource-spring-boot-starter,挺香的!苞米豆的多数据源 → dynamic-datasource-spring-boot-starter,挺香的!
<?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.lee</groupId>
    <artifactId>mybatis-plus-dynamic-datasource</artifactId>
    <version>1.0-SNAPSHOT</version>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.2.10.RELEASE</version>
    </parent>

    <properties>
        <java.version>1.8</java.version>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <mybatis-plus-boot-starter.version>3.1.1</mybatis-plus-boot-starter.version>
        <mssql-jdbc.version>6.2.1.jre8</mssql-jdbc.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>${mybatis-plus-boot-starter.version}</version>
        </dependency>
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>dynamic-datasource-spring-boot-starter</artifactId>
            <version>${mybatis-plus-boot-starter.version}</version>
        </dependency>
        <!-- MySQL驱动-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>

        <!-- SQL Server 驱动-->
        <dependency>
            <groupId>com.microsoft.sqlserver</groupId>
            <artifactId>mssql-jdbc</artifactId>
            <version>${mssql-jdbc.version}</version>
        </dependency>
    </dependencies>
</project>
View Code

  配置也很简单, application.yml 

苞米豆的多数据源 → dynamic-datasource-spring-boot-starter,挺香的!苞米豆的多数据源 → dynamic-datasource-spring-boot-starter,挺香的!
server:
  port: 8081
spring:
  application:
    name: dynamic-datasource
  datasource:
    dynamic:
      datasource:
        mssql_db:
          driver-class-name: com.microsoft.sqlserver.jdbc.SQLServerDriver
          url: jdbc:sqlserver://10.5.108.225:1433;DatabaseName=datasource_mssql;IntegratedSecurity=false;ApplicationIntent=ReadOnly;MultiSubnetFailover=True
          username: sa
          password: Root#123456
        mysql_db:
          driver-class-name: com.mysql.cj.jdbc.Driver
          url: jdbc:mysql://10.5.108.225:3306/datasource_mysql?useSSL=false&useUnicode=true&characterEncoding=utf-8&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=Asia/Shanghai
          username: root
          password: 123456
      primary: mssql_db
      strict: false

mybatis-plus:
  mapper-locations: classpath:mappers/*.xml
  configuration:
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
View Code

  然后在对应的类或者方法上加上注解 DS("数据源名称") 即可,例如

苞米豆的多数据源 → dynamic-datasource-spring-boot-starter,挺香的!

  我们来看下效果

苞米豆的多数据源 → dynamic-datasource-spring-boot-starter,挺香的!

  是不是很神奇?

苞米豆的多数据源 → dynamic-datasource-spring-boot-starter,挺香的!

  完整代码:mybatis-plus-dynamic-datasource

  原理探究

   @DS 用于指定数据源,可以注解在方法上或类上,同时存在则采用就近原则 方法上注解 优先于 类上注解

  这可不是我瞎说,官方文档就是这么写的

苞米豆的多数据源 → dynamic-datasource-spring-boot-starter,挺香的!

  难道一个 @DS 就有如此强大的功能?你们不信,我也不信,它背后肯定有人!

苞米豆的多数据源 → dynamic-datasource-spring-boot-starter,挺香的!

  那么我们就来揪一揪背后的它

  怎么揪了,这又是个难题,我们先打个断点,看一下调用栈

苞米豆的多数据源 → dynamic-datasource-spring-boot-starter,挺香的!

  点一下,瞬间高潮了,不是,是瞬间清醒了

苞米豆的多数据源 → dynamic-datasource-spring-boot-starter,挺香的!

  红线框住的,分 2 点:1: determineDatasource ,2: DynamicDataSourceContextHolder.push 

  我们先看 determineDatasource 

苞米豆的多数据源 → dynamic-datasource-spring-boot-starter,挺香的!

  1、获取 Method 对象

  2、该方法上是否有 DS 注解,有则取方法的 DS 注解,没有则取方法对应的类上的 DS 注解;这个看明白了没?

  3、获取注解的值,也就是 @DS("mysql_db") 中的 mysql_db 

  4、如果数据源名不为空并且数据原名以动态前缀(#)开头,则你们自己去跟 dsProcessor.determineDatasource 

苞米豆的多数据源 → dynamic-datasource-spring-boot-starter,挺香的!

    否则则直接返回数据源名

  针对案例的话,这里肯定是返回类上的数据源名(方法上没有指定数据源,也没有以动态前缀开头)

  我们再来看看 DynamicDataSourceContextHolder.push 

苞米豆的多数据源 → dynamic-datasource-spring-boot-starter,挺香的!

  很简单,但 LOOKUP_KEY_HOLDER 很有意思

苞米豆的多数据源 → dynamic-datasource-spring-boot-starter,挺香的!

  是一个栈,而非楼主在spring集成mybatis实现mysql读写分离 采用的

苞米豆的多数据源 → dynamic-datasource-spring-boot-starter,挺香的!

  至于为什么,人家注释已经写的很清楚了,试问楼主的实现能满足一级一级数据源切换的调用场景吗?

  但不管怎么说, LOOKUP_KEY_HOLDER 的类型还是 ThreadLocal 

  接下来该分析什么?

苞米豆的多数据源 → dynamic-datasource-spring-boot-starter,挺香的!

  我们回顾下:原理解密 → Spring AOP 实现动态数据源(读写分离),底层原理是什么

  直接跳到总结

苞米豆的多数据源 → dynamic-datasource-spring-boot-starter,挺香的!

   框住的 3 条,上面的 2 条在上面已经分析过了把,是不是?你回答是就完事了

苞米豆的多数据源 → dynamic-datasource-spring-boot-starter,挺香的!

  注意,楼主的 DynamicDataSource 是自实现的类,继承了 spring-jdbc 的 AbstractRoutingDataSource 

苞米豆的多数据源 → dynamic-datasource-spring-boot-starter,挺香的!

  那我们就找 AbstractRoutingDataSource 的实现类呗

苞米豆的多数据源 → dynamic-datasource-spring-boot-starter,挺香的!

  发现它就一个实现类,并且是在 spring-jdbc 下,而不是在 com.baomidou 下

  莫非苞米豆有自己的 AbstractRoutingDataSource ? 我们来看看 AbstractDataSource 的实现类有哪些

苞米豆的多数据源 → dynamic-datasource-spring-boot-starter,挺香的!

  看到了没,那么我们接下来就分析它

苞米豆的多数据源 → dynamic-datasource-spring-boot-starter,挺香的!

  内容很简单,最重要的 determineDataSource 还是个抽象方法,那没办法了,看它有哪些子类实现

苞米豆的多数据源 → dynamic-datasource-spring-boot-starter,挺香的!

   DynamicRoutingDataSource 的 determineDataSource 方法如下

苞米豆的多数据源 → dynamic-datasource-spring-boot-starter,挺香的!

    DynamicDataSourceContextHolder 有没有感觉到熟悉?

  想想它的 ThreadLocal<Deque<String>> LOOKUP_KEY_HOLDER ,回忆上来了没?

  出栈,获取到当前的数据源名;接下来该分析谁了?

  那肯定是 getDataSource 方法

苞米豆的多数据源 → dynamic-datasource-spring-boot-starter,挺香的!

  1、如果数据源为空,那么直接返回默认数据源,对应配置文件中的

苞米豆的多数据源 → dynamic-datasource-spring-boot-starter,挺香的!

  2、分组数据源,我们的示例代码那么简单,应该没涉及到这个,先不管

  3、所有数据源,是一个 LinkHashMap ,key 是 数据源名 ,value 是数据源

    可想而知,我们示例的数据源获取就是从该 map 获取的

  4、是否启用严格模式,默认不启动。严格模式下未匹配到数据源直接报错,,非严格模式下则使用默认数据源 primary 所设置的数据源

  5、对应 4,未开启严格模式,未匹配到数据源则使用 primary 所设置的数据源

  那现在又该分析谁?肯定是 dataSourceMap 的值是怎么 put 进去的

  我们看哪些地方用到了 dataSourceMap 

苞米豆的多数据源 → dynamic-datasource-spring-boot-starter,挺香的!

  发现就一个地方进行了 put 

苞米豆的多数据源 → dynamic-datasource-spring-boot-starter,挺香的!

  那这个 addDataSource 方法又在哪被调用了?

苞米豆的多数据源 → dynamic-datasource-spring-boot-starter,挺香的!

   DynamicRoutingDataSource 实现了 InitializingBean ,所以在启动过程中,它的 afterPropertiesSet 方法会被调用,至于为什么,大家自行去查阅

  接下来该分析什么?那肯定是 Map<String, DataSource> dataSources = provider.loadDataSources(); 

  我们跟进 loadDataSources() ,发现有两个类都有该方法

苞米豆的多数据源 → dynamic-datasource-spring-boot-starter,挺香的!

  那么我们应该跟谁?有两种方法

  1、凭感觉,我们的配置文件是 yml 

  2、打断点,重新启动项目,一目了然

苞米豆的多数据源 → dynamic-datasource-spring-boot-starter,挺香的!

   YmlDynamicDataSourceProvider 的 loadDataSources 方法如下

苞米豆的多数据源 → dynamic-datasource-spring-boot-starter,挺香的!

  (这里留个疑问: dataSourcePropertiesMap 存放的是什么,值是如何 put 进去的?

  继续往下跟 createDataSourceMap 方法

苞米豆的多数据源 → dynamic-datasource-spring-boot-starter,挺香的!

  1、配置文件中的数据源属性,断点下就很清楚了

苞米豆的多数据源 → dynamic-datasource-spring-boot-starter,挺香的!

  2、根据数据源属性创建数据源,然后放进 dataSourceMap 中

  创建数据源的过程就不跟了,感兴趣的自行去研究

  至此,不知道大家清楚了没? 我反正是晕了

苞米豆的多数据源 → dynamic-datasource-spring-boot-starter,挺香的!

总结

  1、万变不离其宗,多数据源的原理是不变的

    原理解密 → Spring AOP 实现动态数据源(读写分离),底层原理是什么

  2、苞米豆的多数据源的自动配置类

    com.baomidou.dynamic.datasource.spring.boot.autoconfigure.DynamicDataSourceAutoConfiguration

    这个配置类很重要,很多重要的对象都是在这里注入到 Spring 容器中的

    关于自动配置,大家可参考:springboot2.0.3源码篇 - 自动配置的实现,发现也不是那么复杂

  3、遇到问题,不要立马一头扎进去,自己实现,多查查,看是否有现成的第三方实现

    自己实现,很容易踩别人踩过的坑,容易浪费时间;另外局限性太大,不易拓展,毕竟一人之力有限文章来源地址https://www.toymoban.com/news/detail-420104.html

到了这里,关于苞米豆的多数据源 → dynamic-datasource-spring-boot-starter,挺香的!的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

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

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

相关文章

  • 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日
    浏览(41)
  • Spring | 基于SpringBoot的多数据源实战 - 使用seata实现多数据源的全局事务管理

    在软件开发中, 多数据源 的应用越来越普遍,特别是在 微服务架构 和 业务模块化 的场景下。多数据源能够让不同的业务模块和微服务拥有各自独立的数据存储,大大提高了系统的灵活性和可维护性。本文将深入探讨多数据源的配置和实施,以及在 Spring Boot 环境下,如何通

    2024年02月07日
    浏览(60)
  • springboot整合多数据源的配置以及动态切换数据源,注解切换数据源

    在许多应用程序中,可能需要使用多个数据库或数据源来处理不同的业务需求。Spring Boot提供了简便的方式来配置和使用多数据源,使开发人员能够轻松处理多个数据库连接。如果你的项目中可能需要随时切换数据源的话,那我这篇文章可能能帮助到你 ℹ️:这里对于pom文件

    2024年02月10日
    浏览(49)
  • NamedParameterJdbcTemplate多数据源指定数据源

    实战例子记录 pom config NamedParameterJdbcTemplate(动态sql调用)

    2024年02月08日
    浏览(50)
  • 数据源作用以及spring配置数据源

    数据源,简单理解为数据源头,提供了应用程序所需要数据的位置。数据源保证了应用程序与目标数据之间交互的规范和协议,它可以是数据库,文件系统等等。其中数据源定义了位置信息,用户验证信息和交互时所需的一些特性的配置,同时它封装了如何建立与数据源的连

    2024年02月07日
    浏览(53)
  • SpringBoot——动态数据源(多数据源自动切换)

    日常的业务开发项目中只会配置一套数据源,如果需要获取其他系统的数据往往是通过调用接口, 或者是通过第三方工具比如kettle将数据同步到自己的数据库中进行访问。 但是也会有需要在项目中引用多数据源的场景。比如如下场景: 自研数据迁移系统,至少需要新、老两

    2024年02月16日
    浏览(39)
  • SpringBoot从数据库读取数据数据源配置信息,动态切换数据源

            首先准备多个数据库,主库smiling-datasource,其它库test1、test2、test3         接下来,我们在主库smiling-datasource中,创建表databasesource,用于存储多数据源相关信息。表结构设计如下         创建好表之后,向表databasesource中存储test1、test2、test3三个数据库的相关配置

    2024年01月16日
    浏览(64)
  • 【Spring Boot 3】【数据源】自定义多数据源

    软件开发是一门实践性科学,对大多数人来说,学习一种新技术不是一开始就去深究其原理,而是先从做出一个可工作的DEMO入手。但在我个人学习和工作经历中,每次学习新技术总是要花费或多或少的时间、检索不止一篇资料才能得出一个可工作的DEMO,这占用了我大量的时

    2024年02月01日
    浏览(60)
  • 【Spring Boot 3】【数据源】自定义JPA数据源

    软件开发是一门实践性科学,对大多数人来说,学习一种新技术不是一开始就去深究其原理,而是先从做出一个可工作的DEMO入手。但在我个人学习和工作经历中,每次学习新技术总是要花费或多或少的时间、检索不止一篇资料才能得出一个可工作的DEMO,这占用了我大量的时

    2024年01月21日
    浏览(70)
  • 【Spring Boot 3】【数据源】自定义JDBC多数据源

    软件开发是一门实践性科学,对大多数人来说,学习一种新技术不是一开始就去深究其原理,而是先从做出一个可工作的DEMO入手。但在我个人学习和工作经历中,每次学习新技术总是要花费或多或少的时间、检索不止一篇资料才能得出一个可工作的DEMO,这占用了我大量的时

    2024年01月23日
    浏览(49)

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

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

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

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

二维码1

领取红包

二维码2

领红包