Mybatis动态数据源
今天遇到一个业务上的需求,因为线上数据库磁盘空间已经接近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动态数据源相关推荐
- mybatis动态数据源配置(附自定义注解实现数据源切换)
在做DB数据迁移需求的时候要用到多数据源,正好整理下 实际用到以下几个类 配置文件 #端口 server.port: 8080 spring.application.name: lzqdemo# my ...
- Mybatis动态数据源实现
Mybatis数据库文件配置是在项目启动时初始化数据工厂的,初始化过程仅为1次,当数据库地址改变时需修改配置文件重新启动项目,无法动态加载数据源. Mybatis连接数据库底层核心库SqlSessi ...
- SpringBoot集成Mybatis动态多数据源后,MybatisPlus的IPage失效的问题解决方案
背景 之前做数据抽取的时候,搭了一个mybatis动态数据源切换的架子.方便他们写抽取的代码.今天同事问我,架子里面的mybatisplus的IPage失效了是什么问题.想了一下,应该是写动态数据源的 ...
- mybatis 实现动态数据源连接
mybatis 动态数据源 : springboot项目yml配置: spring: application: name: name # autoconfigure: exclude: com.ali ...
- 动态数据源配置druid+mybatis
本方案不限数据库数量完全动态配置,支持不同的数据库部署在不同的服务器上.(mybatis-plus没测试,下个版本用oracle配的时候尝试plus) 一 .这次我们使用Mysql,本地现在有两个个数 ...
- mysql双数据源动态切换_Spring boot+Mybatis多数据源动态切换
通过重写AbstractRoutingDataSource类中方法determineTargetDataSource,determineCurrentLookupKey,afterProperties ...
- SpringBoot+Mybatis 实现动态数据源切换方案
背景 最近让我做一个大数据的系统,分析了一下,麻烦的地方就是多数据源切换抽取数据.考虑到可以跨服务器跨数据库抽数,再整理数据,就配置了这个动态数据源的解决方案.在此分享给大家. 实现方案 数据库配置文 ...
- Spring Boot + Mybatis 实现动态数据源
动态数据源 在很多具体应用场景的时候,我们需要用到动态数据源的情况,比如多租户的场景,系统登录时需要根据用户信息切换到用户对应的数据库.又比如业务A要访问A数据库,业务B要访问B数据库等,都可以使用动 ...
- Spring Boot + Mybatis多数据源和动态数据源配置
转载自 http://blog.csdn.net/neosmith/article/details/61202084 网上的文章基本上都是只有多数据源或只有动态数据源,而最近的项目需要同时使用两种方式 ...
- mysql动态配置数据源_Spring整合Mybatis实现动态数据源切换教程配置
一.摘要 这篇文章将介绍Spring整合Mybatis 如何完成SqlSessionFactory的动态切换的.并且会简单的介绍下MyBatis整合Spring中的官方的相关代码. Spring整合M ...
最新文章
- LeetCode 601. Human Traffic of Stadium
- 十年web老兵整理的web前端文章
- boost::mp11::mp_none_of_q相关用法的测试程序
- 4.类型设计规范《.NET设计规范》
- .NET的一点历史故事:招兵买马和聚义山林
- YBTOJ:斐波拉契(矩阵快速幂)
- linux 进程的执行时间,Linux 获取进程执行时间
- 【算法精讲】分享一道很不错的算法题
- ceiling和floor转化
- python模块request怎么安装_安装 request模块
- python作用域的顺序_“Python”函数的参数和范围,及其,作用域
- LAMP+Varnish缓存详解(一)——Varnish简介
- 实用Python程序设计测验 - 007:反向输出一个三位数
- 圆柱体积怎么算立方公式_圆柱体积公式是什么,怎么算,
- 查询MAC地址和接口的对应关系
- JavaSE-day01
- 2022年驾驶员考试推土机司机多选题专项训练及答案
- 后台多条sql查询,json传前台,前台处理多条sql数据实例
- 战地4如何修改服务器,战地4如何修改服务器地址
- 工程师在美国为何成职场上的香饽饽(转自新浪乔磊)
热门文章
- 复旦大学肖仰华教授在线授课!从专家系统到知识图谱演进
- 3. tensorflow2实现两总体样本尺度、位置、分布检验问题 ——python实战
- Matplotlib Toolkits:三维绘图工具包matplotlib.mplot3d
- qq浏览文件服务器,腾讯浏览服务
- mysql 变量类型_MySQL 变量类型
- 如何提高go代码覆盖率_如何提高代码质量?
- 力扣-240 搜索二维矩阵 II
- 蓝桥杯2016年第七届C/C++省赛B组第九题-交换瓶子
- 蓝桥杯2015年第六届C/C++省赛A组第八题-饮料换购
- Dart基础第12篇:一个类实现多个接口 以及Dart中的Mixins