背景

最近让我做一个大数据的系统,分析了一下,麻烦的地方就是多数据源切换抽取数据。考虑到可以跨服务器跨数据库抽数,再整理数据,就配置了这个动态数据源的解决方案。在此分享给大家。

实现方案

数据库配置文件

我们项目使用的是yml形式的配置文件,采用的是hikari的数据库连接池。第一步我们自然是配置多个数据库源头。
我们找到spring的datasource,在下方配置三个数据源。

spring:application:name: dynamicDatasourcedatasource:test1:driver-class-name: com.mysql.jdbc.Driverurl: jdbc:mysql://127.0.0.1:3306/test1?serverTimezone=GMT%2B8&characterEncoding=utf-8&useSSL=falseusername: rootpassword: 123456test2:driver-class-name: com.mysql.jdbc.Driverurl: jdbc:mysql://127.0.0.1:3306/test2?serverTimezone=GMT%2B8&characterEncoding=utf-8&useSSL=falseusername: rootpassword: 123456test3:driver-class-name: com.mysql.jdbc.Driverurl: jdbc:mysql://127.0.0.1:3306/test3?serverTimezone=GMT%2B8&characterEncoding=utf-8&useSSL=falseusername: rootpassword: 123456hikari: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")@Primarypublic 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();}
}
package cn.chinaunicom.sdsi.utils;import cn.chinaunicom.sdsi.config.dynamicDataSourceConfig.DatabaseContextHolder;
import cn.chinaunicom.sdsi.config.dynamicDataSourceConfig.DatabaseType;/***  @Description:封装数据源选择*/
public class DynamicDataSourceUtils {public static void chooseBasicDataSource(){DatabaseContextHolder.setDatabaseType(DatabaseType.basic);}public static void chooseBranchDataSource(){DatabaseContextHolder.setDatabaseType(DatabaseType.branch);}}

提供一个示例

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);//数据源切换为branchSystem.out.println("-----数据源为test2");DynamicDataSourceUtils.chooseBranchDataSource();Integer nameCount = demoMapper.getNameCount();Integer ageCount = demoMapper.getAgeCount();System.out.println("nameCount:"+nameCount);System.out.println("ageCount:"+ageCount);//数据源为basicSystem.out.println("-----数据源为test3");DynamicDataSourceUtils.chooseBasicDataSource();Integer ageCount1 = demoMapper.getAgeCount();System.out.println("ageCount:"+ageCount1);}

总结

至此实现了多数据源的动态切换。可以在同一个方法里面进行操作多个数据源。

SpringBoot+Mybatis 实现动态数据源切换方案相关推荐

  1. SpringBoot 优雅实现动态数据源切换配置

    点击关注公众号,利用碎片时间学习 前言 随着应用用户数量的增加,相应的并发请求的数量也会跟着不断增加,慢慢地,单个数据库已经没有办法满足我们频繁的数据库操作请求了,在某些场景下,我们可能会需要配置多个 ...

  2. SpringBoot+MyBatis(动态数据源/分布式事务XA(Atomikos))

    快速集成工具,欢迎打脸 说明 适用环境:SpringBoot / MyBatis / Atomickos  特性: 多数据源,动态切换 多数据源,XA分布式事务支持(需引入Atomickos) 仅支持 ...

  3. mysql动态配置数据源_Spring整合Mybatis实现动态数据源切换教程配置

    一.摘要 这篇文章将介绍Spring整合Mybatis 如何完成SqlSessionFactory的动态切换的.并且会简单的介绍下MyBatis整合Spring中的官方的相关代码. Spring整合M ...

  4. SpringBoot多数据源切换,AOP实现动态数据源切换

    SpringBoot多数据源切换,AOP实现动态数据源切换 操作数据一般都是在DAO层进行处理,可以选择直接使用JDBC进行编程 或者是使用多个DataSource 然后创建多个SessionFact ...

  5. Spring Boot + Mybatis 配合 AOP 和注解实现动态数据源切换配置

    Spring Boot + Mybatis 配合 AOP 和注解实现动态数据源切换配置 前言: 1. 数据库准备: 2. 环境准备: 3.代码部分 4. 测试: 5.等等 6.配合注解实现 7 .测试 ...

  6. springboot动态数据源切换(多数据源配置)

    动态数据源切换即多数据源切换,由于业务的需要或者历史的遗留等原因,一个项目中配置了多个数据库,用于查询不同类型的数据,因此我们就需要经常在各个库中切换数据源,接下来我们将进行具体的说明: 项目结构如下 ...

  7. Spring Boot + Mybatis 实现动态数据源

    动态数据源 在很多具体应用场景的时候,我们需要用到动态数据源的情况,比如多租户的场景,系统登录时需要根据用户信息切换到用户对应的数据库.又比如业务A要访问A数据库,业务B要访问B数据库等,都可以使用动 ...

  8. 动态数据源切换--AbstractRoutingDataSource

    转载自http://blog.csdn.net/x2145637/article/details/52461198 在Spring 2.0.1中引入了AbstractRoutingDataSource ...

  9. spring environment_程序员:Spring项目中简单几步实现多个动态数据源切换

    每一个请求与其他的用户是面对不同的数据库,这就需要用到动态数据源切换,来满足不同数据库.不同数据表(不同数据源)的灵活调用. 动态数据源切换 满足mysql.oracle等主流数据库进行动态数据源切换 ...

最新文章

  1. 部分和问题 (dfs搜索 尺取)
  2. 点标记 高德地图_打尽渣男渣女的查岗神器?高德家人地图实测
  3. c++问题,EOF eofbit eof() 请问他们的区别是什么?
  4. [HTTP] Cookie
  5. bash:附近有语法错误_Bash备忘单:按键组合和特殊语法
  6. 介绍家乡网页html代码_「HTML一」 html基础
  7. (计算机显示器主屏幕区域)桌面造句,部编版《语文园地四》教学反思模板(11页)-原创力文档...
  8. lisp 多段线转面域_Objectarx 相交矩形求并集 面域转多段线
  9. 局域网计算机无法配置网关,在内网中,为什么不设置“默认网关”计算机也能互相通讯?...
  10. win10和ubuntu双系统下彻底删除ubuntu系统和grub引导
  11. protobuf如何使用Protogen工具生成CS代码详细教学篇
  12. c++、7-5 估算数学常数e的值
  13. BigDecimal
  14. IE8的调试工具使用详解
  15. Oracle 出生日期算年龄
  16. 产品营销策划方案怎么写?,总结4步!
  17. UltraISO PE(软碟通) v9.6.2.3059 注册码
  18. 建筑工程造价常见的41个问题
  19. 《乔布斯传记》读后感(三)------乔布斯的遗产
  20. REST(Representational State Transfer):表述性状态转移

热门文章

  1. 我是非计算机专业学生,非计算机专业学生怎么走上计算机技术之路?
  2. php屏幕抓取,PHP抓屏函数实现屏幕快照代码分享
  3. 2021 年 5 月中国编程语言排行榜,C++ 超过 Java 没戏了...
  4. 费解!为什么那么多人用“ji32k7au4a83”作密码?
  5. 每日一皮:强大的sudo ...
  6. Apache的架构师们遵循的30条设计原则
  7. 我说分布式事务之消息最终一致性事务(一):原理及实现
  8. 华理c语言设计网上作业,华东理工大学第一学年第二学期网上作业参考答案C语言设计1...
  9. 八字喜用神php源码,免费查八字喜用神的软件 通关用神
  10. PaddleDetection 个人测评