SpringBoot+Mybatis 实现动态数据源切换方案
背景
最近让我做一个大数据的系统,分析了一下,麻烦的地方就是多数据源切换抽取数据。考虑到可以跨服务器跨数据库抽数,再整理数据,就配置了这个动态数据源的解决方案。在此分享给大家。
实现方案
数据库配置文件
我们项目使用的是yml形式的配置文件,采用的是hikari的数据库连接池。第一步我们自然是配置多个数据库源头。
我们找到spring的datasource,在下方配置三个数据源。
spring:
application:
name: dynamicDatasource
datasource:
test1:
driver-class-name: com.mysql.jdbc.Driver
url: jdbc:mysql://127.0.0.1:3306/test1?serverTimezone=GMT%2B8&characterEncoding=utf-8&useSSL=false
username: root
password: 123456
test2:
driver-class-name: com.mysql.jdbc.Driver
url: jdbc:mysql://127.0.0.1:3306/test2?serverTimezone=GMT%2B8&characterEncoding=utf-8&useSSL=false
username: root
password: 123456
test3:
driver-class-name: com.mysql.jdbc.Driver
url: jdbc:mysql://127.0.0.1:3306/test3?serverTimezone=GMT%2B8&characterEncoding=utf-8&useSSL=false
username: root
password: 123456
hikari:
leak-detection-threshold: 2000
定义数据源实体类
我们可以建立个datasourceBean文件夹专门管理数据源的实体类。
我们这里要建立三个实体类。分别对应test1,test2,test3
@Configuration
public class Test1DataSourceBean {
@Value("${spring.datasource.test1.driver-class-name}")
private String test1Driver;
@Value("${spring.datasource.test1.url}")
private String test1Url;
@Value("${spring.datasource.test1.username}")
private String test1Username;
@Value("${spring.datasource.test1.password}")
private String test1Password;
@Bean(name="test1DataSource")
public DataSource test1DataSource() throws Exception{
HikariDataSource dataSource = new HikariDataSource();
dataSource.setDriverClassName(test1Driver);
dataSource.setJdbcUrl(test1Url);
dataSource.setUsername(test1Username);
dataSource.setPassword(test1Password);
return dataSource;
}
}
@Configuration
public class Test2DataSourceBean {
@Value("${spring.datasource.test2.driver-class-name}")
private String test2Driver;
@Value("${spring.datasource.test2.url}")
private String test2Url;
@Value("${spring.datasource.test2.username}")
private String test2Username;
@Value("${spring.datasource.test2.password}")
private String test2Password;
@Bean(name="test2DataSource")
public DataSource test2DataSource() throws Exception{
HikariDataSource dataSource = new HikariDataSource();
dataSource.setDriverClassName(test2Driver);
dataSource.setJdbcUrl(test2Url);
dataSource.setUsername(test2Username);
dataSource.setPassword(test2Password);
return dataSource;
}
}
@Configuration
public class Test3DataSourceBean {
@Value("${spring.datasource.test3.driver-class-name}")
private String test3Driver;
@Value("${spring.datasource.test3.url}")
private String test3Url;
@Value("${spring.datasource.test3.username}")
private String test3Username;
@Value("${spring.datasource.test3.password}")
private String test3Password;
@Bean(name="test3DataSource")
public DataSource test3DataSource() throws Exception{
HikariDataSource dataSource = new HikariDataSource();
dataSource.setDriverClassName(test3Driver);
dataSource.setJdbcUrl(test3Url);
dataSource.setUsername(test3Username);
dataSource.setPassword(test3Password);
return dataSource;
}
}
定义一个枚举类管理数据源
public enum DatabaseType {
test1("test1", "test1"),
test2("test2", "test2"),
test3("test3","test3");
private String name;
private String value;
DatabaseType(String name, String value){
this.name = name;
this.value = value;
}
public String getName(){
return name;
}
public String getValue(){
return value;
}
}
定义一个线程安全的数据源容器
public class DatabaseContextHolder {
private static final ThreadLocal<DatabaseType> contextHolder = new ThreadLocal<>();
public static void setDatabaseType(DatabaseType type){
contextHolder.set(type);
}
public static DatabaseType getDatabaseType(){
return contextHolder.get();
}
}
定义动态数据源
public class DynamicDataSource extends AbstractRoutingDataSource{
protected Object determineCurrentLookupKey() {
return DatabaseContextHolder.getDatabaseType();
}
}
mybatis配置类
网上的很多文章配置出来都会产生数据源循环依赖的问题,这里解决了这个问题。
@Configuration
@MapperScan(basePackages="cn.test.jichi", sqlSessionFactoryRef="sessionFactory")
public class MybatisConfig {
/**
* @Description:设置动态数据源
*/
@Bean(name="dynamicDataSource")
@Primary
public DynamicDataSource DataSource(
@Qualifier("test1DataSource") DataSource test1DataSource,
@Qualifier("test2DataSource") DataSource test2DataSource,
@Qualifier("test3DataSource") DataSource test3DataSource){
Map<Object, Object> targetDataSource = new HashMap<>();
targetDataSource.put(DatabaseType.test1, test1DataSource);
targetDataSource.put(DatabaseType.test2, test2DataSource);
targetDataSource.put(DatabaseType.test3, test3DataSource);
DynamicDataSource dataSource = new DynamicDataSource();
dataSource.setTargetDataSources(targetDataSource);
dataSource.setDefaultTargetDataSource(test1DataSource);
return dataSource;
}
/**
* @Description:根据动态数据源创建sessionFactory
*/
@Bean(name="sessionFactory")
public SqlSessionFactory sessionFactory(
@Qualifier("test1DataSource") DataSource test1DataSource,
@Qualifier("test2DataSource") DataSource test2DataSource,
@Qualifier("test3DataSource") DataSource test3DataSource) throws Exception{
SqlSessionFactoryBean sessionFactoryBean = new SqlSessionFactoryBean();
//构造方法,解决动态数据源循环依赖问题。
sessionFactoryBean.setDataSource(this.DataSource(test1DataSource,test2DataSource, test3DataSource));
return sessionFactoryBean.getObject();
}
}
提供一个示例
public void testDymnaicDatasource(){
//不切换数据源默认是自己的。
System.out.println("-----默认数据源");
DemoEntity totalCount = demoMapper.getTotalCount();
String nameCount1 = totalCount.getNameCount();
String ageCount2 = totalCount.getAgeCount();
System.out.println("nameCount:"+nameCount1);
System.out.println("ageCount:"+ageCount2);
//数据源切换为branch
System.out.println("-----数据源为test2");
DynamicDataSourceUtils.chooseBranchDataSource();
Integer nameCount = demoMapper.getNameCount();
Integer ageCount = demoMapper.getAgeCount();
System.out.println("nameCount:"+nameCount);
System.out.println("ageCount:"+ageCount);
//数据源为basic
System.out.println("-----数据源为test3");
DynamicDataSourceUtils.chooseBasicDataSource();
Integer ageCount1 = demoMapper.getAgeCount();
System.out.println("ageCount:"+ageCount1);
}
总结
至此实现了多数据源的动态切换。可以在同一个方法里面进行操作多个数据源。
SpringBoot+Mybatis 实现动态数据源切换方案的更多相关文章
- SpringBoot学习笔记:动态数据源切换
SpringBoot学习笔记:动态数据源切换 数据源 Java的javax.sql.DataSource接口提供了一种处理数据库连接的标准方法.通常,DataSource使用URL和一些凭据来建立数据 ...
- SpringBoot和Mycat动态数据源项目整合
SpringBoot项目整合动态数据源(读写分离) 1.配置多个数据源,根据业务需求访问不同的数据,指定对应的策略:增加,删除,修改操作访问对应数据,查询访问对应数据,不同数据库做好的数据一致性的处理 ...
- Spring Boot + Mybatis 实现动态数据源
动态数据源 在很多具体应用场景的时候,我们需要用到动态数据源的情况,比如多租户的场景,系统登录时需要根据用户信息切换到用户对应的数据库.又比如业务A要访问A数据库,业务B要访问B数据库等,都可以使用动 ...
- Spring 实现动态数据源切换--转载 (AbstractRoutingDataSource)的使用
[参考]Spring(AbstractRoutingDataSource)实现动态数据源切换--转载 [参考] 利用Spring的AbstractRoutingDataSource解决多数据源的问题 ...
- Spring主从数据库的配置和动态数据源切换原理
原文:https://www.liaoxuefeng.com/article/00151054582348974482c20f7d8431ead5bc32b30354705000 在大型应用程序中,配 ...
- SpringMVC 利用AbstractRoutingDataSource实现动态数据源切换
SpringMVC 利用AbstractRoutingDataSource实现动态数据源切换 本文转载至:http://exceptioneye.iteye.com/blog/1698064 Spri ...
- 【开发笔记】- AbstractRoutingDataSource动态数据源切换,AOP实现动态数据源切换
AbstractRoutingDataSource动态数据源切换 上周末,室友通宵达旦的敲代码处理他的多数据源的问题,搞的非常的紧张,也和我聊了聊天,大概的了解了他的业务的需求.一般的情况下我们都是使 ...
- AbstractRoutingDataSource动态数据源切换,AOP实现动态数据源切换
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明.本文链接:https://blog.csdn.net/u012881904/article/de ...
- 30个类手写Spring核心原理之动态数据源切换(8)
本文节选自<Spring 5核心原理> 阅读本文之前,请先阅读以下内容: 30个类手写Spring核心原理之自定义ORM(上)(6) 30个类手写Spring核心原理之自定义ORM(下)( ...
随机推荐
- spring boot 长时间运行上传报临时目录找不到
The temporary upload location [/tmp/tomcat-docbase.3752410576653354473.8899/work/Tomcat/localhost/RO ...
- NOIP模拟30B 活该
T1:没有判-1 T2:推出柿子之后手摸错了!,只交了一个表 T3....... 完戏!,就是活该!
- C语言程序设计100例之(4):水仙花数
例4 水仙花数 题目描述 一个三位整数(100-999),若各位数的立方和等于该数自身,则称其为“水仙花数”(如:153=13+53+33),找出所有的这种数. 输入格式 没有输入 输出格式 若 ...
- IPv6笔记-地址结构与分类
1.地址基础 IPv6地址由被划分为8个16位块的128位组成. 然后将每个块转换为由冒号符号分隔的4位十六进制数字. 2001::3238:00E1:0063:0000:0000:FEFB 每一块多 ...
- go中的数据结构字典-map
1. map的使用 golang中的map是一种数据类型,将键与值绑定到一起,底层是用哈希表实现的,可以快速的通过键找到对应的值. 类型表示:map[keyType][valueType] key一定 ...
- Python数据可视化之matplotlib
常用模块导入 import numpy as np import matplotlib import matplotlib.mlab as mlab import matplotlib.pyplot ...
- 基于Docker的Mysql主从复制
基于Docker的Mysql主从复制搭建 为什么基于Docker搭建? 资源有限 虚拟机搭建对机器配置有要求,并且安装mysql步骤繁琐 一台机器上可以运行多个Docker容器 Docker容器之间相 ...
- (C#)WPF:LinearGradientBrush 线性渐变画刷和RadialGradientBrush 圆形渐变画刷
<Window x:Class="WpfApp1.MainWindow" xmlns="http://schemas.microsoft.com/winfx/200 ...
- spark集群搭建(三台虚拟机)——spark集群搭建(5)
!!!该系列使用三台虚拟机搭建一个完整的spark集群,集群环境如下: virtualBox5.2.Ubuntu14.04.securecrt7.3.6_x64英文版(连接虚拟机) jdk1.7.0. ...
- linux添加、删除、升级软件包 yum rpm dpkg
1.红帽7主要采用yum和rpm SN command 1 rpm -qa --query --all. 2 rpm -ql <package> 列出包中的文件 3 rpm -ivh ...