今天遇到一个业务上的需求,因为线上数据库磁盘空间已经接近3个T,想到的一个解决方案是对线上分库分表的64个库做物理拆分,其中编号1-32库放到一个物理空间,33-64库放到一个物理空间。

网上的方案大致有二种:

1.将不同库操作分开放进不同的mapper,配置两个数据源 

2. 配置动态数据源,使用aop进行动态切换,真正实现动态数据源

很显然我的系统都是同一套mapper对象,不能拆分,因此采用第二种,一般第二种比较多用于实现读写分离,但是这里我用来做拆分分库分表

其中一个系统因为用的当当的sharding-jdbc做的分库分表,直接修改1-32库的数据库url指向新的地址,另外一个因为用的dbcp的基础BasicDataSource,这里给出实现方案:

1. 首先写一个动态数据源对象继承自AbstractRoutingDataSource

public class NewDynamicDataSource extends AbstractRoutingDataSource {private final Logger logger = LoggerFactory.getLogger(NewDynamicDataSource.class);@Overrideprotected Object determineCurrentLookupKey() {logger.info(String.format("数据源为 %s", NewDataSourceContextHolder.getDB()));return NewDataSourceContextHolder.getDB();}
}

2. 然后配置多数据源  其中

mysqlDataSource3和mysqlDataSource4分别是1-32编号的库,33-64编号的库,都是dbcp的Datasource,也可以是DHCP、C3P0、Druid连接池的数据源连接。
 <bean id="dynamicDatasource" class="com.ppdai.realtime.dataservices.dbcp.NewDynamicDataSource"><property name="targetDataSources"><map key-type="java.lang.String"><entry value-ref="mysqlDataSource3" key="db1_32"></entry><entry value-ref="mysqlDataSource4" key="db33_64"></entry></map></property><property name="defaultTargetDataSource" ref="mysqlDataSource3"></property></bean>

3. 第三步 自定义拆分数据库注解

这个注解上有三个属性  tableTotalNum:总表数  pertableNum:每个库表数量

@Target({ ElementType.METHOD, ElementType.TYPE })
@Retention(RetentionPolicy.RUNTIME)
public @interface DBSource {String tableTotalNum() default "64";String pertableNum() default "1";String value() default "db1_32";
}

4. 第四部  数据源设置Holder

  这个Holder用来设置当前线程(当前请求,一个请求一个线程处理)中所使用的datasource 名称,其实这里有个漏洞,如果一个请求需要跨库进行查询,这里是满足不了的,不过我这里业务没有这种情况。

public class DataSourceContextHolder {  private static final ThreadLocal<String> contextHolder = new ThreadLocal<String>();  public static void setDbType(String dbType) {  contextHolder.set(dbType);  }  public static String getDbType() {  return ((String) contextHolder.get());  }  public static void clearDbType() {  contextHolder.remove();  }@Overrideprotected void finalize() throws Throwable {super.finalize();clearDbType();}  }

5. AOP实现 对查询做切面

在有@DBSource注解的方法上做AOP,然后根据方法参数userid做分库分表。逻辑是(userid % 总表数)/ 每个库表数

 @Aspect
@Component
public class DynamicDataSourceAspect {@Before("@annotation(com.ppdai.realtime.dataservices.dbcp.DBSource)")public void beforeSwitchDS(JoinPoint point){//获得当前访问的classClass<?> className = point.getTarget().getClass();//获得访问的方法名String methodName = point.getSignature().getName();//得到方法的参数的类型Class[] argClass = ((MethodSignature)point.getSignature()).getParameterTypes();Object[] args = point.getArgs();String dataSource = NewDataSourceContextHolder.DB_1_32;try {// 得到访问的方法对象Method method = className.getMethod(methodName, argClass);//             判断是否存在@DS注解if (method.isAnnotationPresent(DBSource.class)) {DBSource dbSource = method.getAnnotation(DBSource.class);if(args != null &&args.length != 0){if(args[0] instanceof Integer){Integer userid = (Integer) args[0];if(((userid % Integer.valueOf(dbSource.tableTotalNum()))/Integer.valueOf(dbSource.pertableNum())) < 32){dataSource = NewDataSourceContextHolder.DB_1_32;}else {dataSource = NewDataSourceContextHolder.DB_33_64;}}else if(args[0] instanceof Long){Long userid = (Long) args[0];if(((userid % Integer.valueOf(dbSource.tableTotalNum()))/Integer.valueOf(dbSource.pertableNum())) < 32){dataSource = NewDataSourceContextHolder.DB_1_32;}else {dataSource = NewDataSourceContextHolder.DB_33_64;}}}
            }} catch (Exception e) {e.printStackTrace();}// 切换数据源
        NewDataSourceContextHolder.setDB(dataSource);}@After("@annotation(com.ppdai.realtime.dataservices.dbcp.DBSource)")public void afterSwitchDS(JoinPoint point){NewDataSourceContextHolder.clearDB();}
}

6. 最后就是在需要动态选库的函数上使用@DBSource注解  bingo

@DBSource(tableTotalNum = "2048", pertableNum = "32")public Collection<Emailbills> get***(Integer userid) {  ** }

函数方法体和方法隐去了。

转载于:https://www.cnblogs.com/zhengwangzw/p/9445956.html

Mybatis动态数据源相关推荐

  1. mybatis动态数据源配置(附自定义注解实现数据源切换)

    在做DB数据迁移需求的时候要用到多数据源,正好整理下 实际用到以下几个类 配置文件 #端口 server.port: 8080 spring.application.name: lzqdemo# my ...

  2. Mybatis动态数据源实现

    Mybatis数据库文件配置是在项目启动时初始化数据工厂的,初始化过程仅为1次,当数据库地址改变时需修改配置文件重新启动项目,无法动态加载数据源.  Mybatis连接数据库底层核心库SqlSessi ...

  3. SpringBoot集成Mybatis动态多数据源后,MybatisPlus的IPage失效的问题解决方案

    背景 之前做数据抽取的时候,搭了一个mybatis动态数据源切换的架子.方便他们写抽取的代码.今天同事问我,架子里面的mybatisplus的IPage失效了是什么问题.想了一下,应该是写动态数据源的 ...

  4. mybatis 实现动态数据源连接

    mybatis 动态数据源 : springboot项目yml配置: spring: application: name: name # autoconfigure: exclude: com.ali ...

  5. 动态数据源配置druid+mybatis

    本方案不限数据库数量完全动态配置,支持不同的数据库部署在不同的服务器上.(mybatis-plus没测试,下个版本用oracle配的时候尝试plus) 一 .这次我们使用Mysql,本地现在有两个个数 ...

  6. mysql双数据源动态切换_Spring boot+Mybatis多数据源动态切换

    通过重写AbstractRoutingDataSource类中方法determineTargetDataSource,determineCurrentLookupKey,afterProperties ...

  7. SpringBoot+Mybatis 实现动态数据源切换方案

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

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

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

  9. Spring Boot + Mybatis多数据源和动态数据源配置

    转载自 http://blog.csdn.net/neosmith/article/details/61202084 网上的文章基本上都是只有多数据源或只有动态数据源,而最近的项目需要同时使用两种方式 ...

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

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

最新文章

  1. LeetCode 601. Human Traffic of Stadium
  2. 十年web老兵整理的web前端文章
  3. boost::mp11::mp_none_of_q相关用法的测试程序
  4. 4.类型设计规范《.NET设计规范》
  5. .NET的一点历史故事:招兵买马和聚义山林
  6. YBTOJ:斐波拉契(矩阵快速幂)
  7. linux 进程的执行时间,Linux 获取进程执行时间
  8. 【算法精讲】分享一道很不错的算法题
  9. ceiling和floor转化
  10. python模块request怎么安装_安装 request模块
  11. python作用域的顺序_“Python”函数的参数和范围,及其,作用域
  12. LAMP+Varnish缓存详解(一)——Varnish简介
  13. 实用Python程序设计测验 - 007:反向输出一个三位数
  14. 圆柱体积怎么算立方公式_圆柱体积公式是什么,怎么算,
  15. 查询MAC地址和接口的对应关系
  16. JavaSE-day01
  17. 2022年驾驶员考试推土机司机多选题专项训练及答案
  18. 后台多条sql查询,json传前台,前台处理多条sql数据实例
  19. 战地4如何修改服务器,战地4如何修改服务器地址
  20. 工程师在美国为何成职场上的香饽饽(转自新浪乔磊)

热门文章

  1. 复旦大学肖仰华教授在线授课!从专家系统到知识图谱演进
  2. 3. tensorflow2实现两总体样本尺度、位置、分布检验问题 ——python实战
  3. Matplotlib Toolkits:三维绘图工具包matplotlib.mplot3d
  4. qq浏览文件服务器,腾讯浏览服务
  5. mysql 变量类型_MySQL 变量类型
  6. 如何提高go代码覆盖率_如何提高代码质量?
  7. 力扣-240 搜索二维矩阵 II
  8. 蓝桥杯2016年第七届C/C++省赛B组第九题-交换瓶子
  9. 蓝桥杯2015年第六届C/C++省赛A组第八题-饮料换购
  10. Dart基础第12篇:一个类实现多个接口 以及Dart中的Mixins