摘要:本文模拟一下在主库查询订单信息查询不到的时候,切换数据源去历史库里面查询。

本文分享自华为云社区《springboot动态切换数据源》,作者:小陈没烦恼 。

前言

在公司的系统里,由于数据量较大,所以配置了多个数据源,它会根据用户所在的地区去查询那一个数据库,这样就产生了动态切换数据源的场景。

今天,就模拟一下在主库查询订单信息查询不到的时候,切换数据源去历史库里面查询。

实现效果

首先我们设置查询的数据库为db1,可以看到通过订单号没有查到订单信息,然后我们重置数据源,重新设置为db2,同样的订单号就可以查询到信息。

数据库准备

新建两个数据库db1和db2,db1作为主库,db2作为历史库

两个库中都有一个订单表biz_order,主库中没有数据,历史库中有我们要查询的数据。

代码编写

1.新建一个springboot项目,引入所需依赖

 <dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<!--引入druid-替换默认数据库连接池-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.2.15</version>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.2.2</version>
</dependency>
<!--mysql驱动-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.30</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>

2.application.yaml配置数据库信息

这里我们配置两个数据库的信息

spring:
datasource:
db1:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost/db1?characterEncoding=utf8&characterSetResults=utf8&autoReconnect=true&failOverReadOnly=false
username: root
password: root
type: com.alibaba.druid.pool.DruidDataSource
db2:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost/db2?characterEncoding=utf8&characterSetResults=utf8&autoReconnect=true&failOverReadOnly=false
username: root
password: root
type: com.alibaba.druid.pool.DruidDataSource
mybatis:
mapper-locations: classpath:mapper/*.xml

3.创建数据源对象,并注入spring容器中

新建DynamicDataSourceConfig.java文件,在该配置文件中读取yaml配置的数据源信息,并且通过该信息构造数据源对象,然后通过@Bean注解注入到spring容器中。

package com.it1997.config;
import com.alibaba.druid.pool.DruidDataSource;
import com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceBuilder;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import javax.sql.DataSource;
@Configuration
public class DynamicDataSourceConfig {
@Bean("dataSource1")
@ConfigurationProperties(prefix = "spring.datasource.db1")
public DataSource oneDruidDataSource() {
return DruidDataSourceBuilder.create().build();
}
@Bean("dataSource2")
@ConfigurationProperties(prefix = "spring.datasource.db2")
public DataSource twoDruidDataSource() {
return DruidDataSourceBuilder.create().build();
}
@Bean
public DataSourceTransactionManager dataSourceTransactionManager1(@Qualifier("dataSource1") DataSource dataSource1) {
DataSourceTransactionManager dataSourceTransactionManager = new DataSourceTransactionManager();
dataSourceTransactionManager.setDataSource(dataSource1);
return dataSourceTransactionManager;
}
@Bean
public DataSourceTransactionManager dataSourceTransactionManager2(@Qualifier("dataSource2") DataSource dataSource2) {
DataSourceTransactionManager dataSourceTransactionManager = new DataSourceTransactionManager();
dataSourceTransactionManager.setDataSource(dataSource2);
return dataSourceTransactionManager;
}
}

4.数据源配置上下文信息

新建DynamicDataSourceHolder.java文件,该文件通过ThreadLocal,实现为每一个线程创建一个保存数据源配置的上下文。并且提供setDataSource和getDataSource静态方法来设置和获取数据源的名称。

package com.it1997.config;
public class DynamicDataSourceHolder {
private static final ThreadLocal<String> contextHolder = new ThreadLocal<>();
public static void setDataSource(String dataSource) {
contextHolder.set(dataSource);
}
public static String getDataSource() {
return contextHolder.get();
}
public static void clearDataSource() {
contextHolder.remove();
}
}

5.重写数据源配置类

新建DynamicDataSource.java文件,该类继承AbstractRoutingDataSource 类,重写父类determineCurrentLookupKey和afterPropertiesSet方法。

这里我们重写父类中afterPropertiesSet方法(为什么要重写在这个方法,可以看文章最后对于druid的源码的讲解),在这个方法里我们将spring容器中的所有的数据源,都给放到map里,然后后续我们根据map中的key来获取不同的数据源,super.afterPropertiesSet();通过这个方法设置上数据源。

在类上加上@Primary注解,让spring容器优先使用我们自定义的数据源,否则还是会使用默认的数据源配置。

package com.it1997.config;
import org.springframework.context.annotation.Primary;
import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import javax.sql.DataSource;
import java.util.HashMap;
import java.util.Map;
@Component
@Primary
public class DynamicDataSource extends AbstractRoutingDataSource {
@Resource
DataSource dataSource1;
@Resource
DataSource dataSource2;
@Override
protected Object determineCurrentLookupKey() {
return DynamicDataSourceHolder.getDataSource();
}
@Override
public void afterPropertiesSet() {
// 初始化所有数据源
Map<Object, Object> targetDataSource = new HashMap<>();
targetDataSource.put("db1", dataSource1);
targetDataSource.put("db2", dataSource2);
super.setTargetDataSources(targetDataSource);
super.setDefaultTargetDataSource(dataSource1);
super.afterPropertiesSet();
}
}

druid数据源配置解读

点开我们刚刚继承的AbstractRoutingDataSource抽象类,可以看到它又继承了AbstractDataSource 实现了InitializingBean接口。

然后我们在看一下druid的数据源配置是怎么实现的,点开DruidDataSourceWrapper类,可以看到它也是继承了AbstractDataSource 实现了InitializingBean接口。并且,读取的是yaml文件中spring.datasource.druid下面配置的数据库连接信息。

而我们自定的一的数据源读取的是spring.datasource.db1下面配置的数据库连接信息。

druid的数据源配置,实现了接口中afterPropertiesSet,在这个方法中设置了数据库的基本信息,例如,数据库连接地址、用户名、密码以及数据库连接驱动信息。

点击关注,第一时间了解华为云新鲜技术~

实例讲解Spring boot动态切换数据源的更多相关文章

  1. Spring+Mybatis动态切换数据源

    功能需求是公司要做一个大的运营平台: 1.运营平台有自身的数据库,维护用户.角色.菜单.部分以及权限等基本功能. 2.运营平台还需要提供其他不同服务(服务A,服务B)的后台运营,服务A.服务B的数据库 ...

  2. Spring AOP动态切换数据源

    现在稍微复杂一点的项目,一个数据库也可能搞不定,可能还涉及分布式事务什么的,不过由于现在我只是做一个接口集成的项目,所以分布式就先不用了,用Spring AOP来达到切换数据源,查询不同的数据库就可以 ...

  3. Spring MVC动态切换数据源(多数据库类型)

    最近由于项目需求,需要将Sql Server 和 Mysql 两种数据库整合到一个项目,项目的用到的框架是SSM. 因此尝试了利用AOP切面来切每次执行的Servcie方法,根据Service所在的包 ...

  4. Spring Boot 如何动态切换数据源

    本章是一个完整的 Spring Boot 动态数据源切换示例,例如主数据库使用 lionsea 从数据库 lionsea_slave1.lionsea_slave2.只需要在对应的代码上使用 Data ...

  5. 在使用 Spring Boot 和 MyBatis 动态切换数据源时遇到的问题以及解决方法

    相关项目地址:https://github.com/helloworlde/SpringBoot-DynamicDataSource 1. org.apache.ibatis.binding.Bind ...

  6. Spring + Mybatis 项目实现动态切换数据源

    项目背景:项目开发中数据库使用了读写分离,所有查询语句走从库,除此之外走主库. 最简单的办法其实就是建两个包,把之前数据源那一套配置copy一份,指向另外的包,但是这样扩展很有限,所有采用下面的办法. ...

  7. Spring动态切换数据源及事务

    前段时间花了几天来解决公司框架ssm上事务问题.如果不动态切换数据源话,直接使用spring的事务配置,是完全没有问题的.由于框架用于各个项目的快速搭建,少去配置各个数据源配置xml文件等.采用了动态 ...

  8. Spring学习总结(16)——Spring AOP实现执行数据库操作前根据业务来动态切换数据源

    深刻讨论为什么要读写分离? 为了服务器承载更多的用户?提升了网站的响应速度?分摊数据库服务器的压力?就是为了双机热备又不想浪费备份服务器?上面这些回答,我认为都不是错误的,但也都不是完全正确的.「读写 ...

  9. Spring Boot配置多数据源并实现Druid自动切换

    原文:https://blog.csdn.net/acquaintanceship/article/details/75350653 Spring Boot配置多数据源配置yml文件主数据源配置从数据 ...

  10. Spring Boot与多数据源那点事儿~

    持续原创输出,点击上方蓝字关注我 目录 前言 写这篇文章的目的 什么是多数据源? 何时用到多数据源? 整合单一的数据源 整合Mybatis 多数据源如何整合? 什么是动态数据源? 数据源切换如何保证线 ...

随机推荐

  1. wx.BoxSizer布局管理器用法,及其Add()方法参数说明

    wx.BoxSizer 布局管理器是一种常见的布局管理器,它可以在水平或垂直方向上布置子窗口部件.同时,它还可以在水平或垂直方向上包含其他 wx.BoxSizer 来创建复杂的布局. 下面是 wx.B ...

  2. CSS 高阶小技巧 - 角向渐变的妙用!

    本文将介绍一个角向渐变的一个非常有意思的小技巧! 我们尝试使用 CSS 绘制如下图形: 在之前,类似的图案,其实我们有尝试过,在 单标签实现复杂的棋盘布局 一文中,我们用单标签实现了这样一个棋盘布局: ...

  3. 如何提取 x64 程序那些易失的方法参数

    一:背景 1. 讲故事 最近经常遇到有朋友反馈,在 x64 环境下如何提取线程栈中的方法参数,熟悉 x64 调用协定的朋友应该知道,这种协定范围下,方法的前四个参数都是用寄存器传递的,比如rcx,rd ...

  4. Revit BIM模型在ArcGIS Pro中的数据组织及转换成SLPK后的图层结构解析

    ArcGIS Pro对Revit 数据有自己的一套分层方式. 在ArcGIS Pro中打开bim文件会发现都是按照相同的方式组织数据: 将rvt格式数据转换成SLPK格式后的数据结构(将slpk数据直 ...

  5. cs 保研经验贴 | 综合面试题库

    绝大部分夏令营都需要面试:如果幸运的话,稍微问几个问题就结束了:不幸的话,可能要抓住你做项目.读论文.复现.做 pre 等等. 这篇博客适用于幸运的情况:绝大部分学校的面试题库,都是彼此重合的,并且一 ...

  6. 二进制安装Kubernetes(k8s) v1.22.10 IPv4/IPv6双栈

    二进制安装Kubernetes(k8s) v1.22.10 IPv4/IPv6双栈 Kubernetes 开源不易,帮忙点个star,谢谢了 介绍 kubernetes二进制安装 后续尽可能第一时间更 ...

  7. 近万字总结:Java8 Stream流式处理指南

    总结/朱季谦 在实际项目当中,若能熟练使用Java8 的Stream流特性进行开发,就比较容易写出简洁优雅的代码.目前市面上很多开源框架,如Mybatis- Plus.kafka Streams以及F ...

  8. 基于django+ansible+webssh运维自动化管理系统

    基于django+ansible+webssh运维自动化管理系统   前言 最初开发这个基于Django ansible运维自动化管理系统的想法其实从大学时候就已经有了,但是苦于技术原因和没有线上环境 ...

  9. 数据分析02-(pandas介绍、jupyter notebook)

    数据分析-02 数据分析-02 pandas pandas介绍 pandas核心数据结构 Series DataFrame 核心数据结构操作 复合索引 Jupyter notebook 数据加载 处理 ...

  10. 聊一聊 Valgrind 监视非托管内存泄露和崩溃

    一:背景 1. 讲故事 只要是程序总会出现各种莫名其妙的问题,比如:非托管内存泄露,程序崩溃,在 Windows 平台上一般用微软自家的官方工具 App Verifier 就可以洞察,那问题出在 Li ...