import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;

public class DynamicDataSource extends AbstractRoutingDataSource{

	@Override
protected Object determineCurrentLookupKey(){
return DynamicDataSourceHolder.getDbType();
}
}

  

import org.slf4j.LoggerFactory;
import org.slf4j.Logger; public class DynamicDataSourceHolder {
private static Logger logger=LoggerFactory.getLogger(DynamicDataSourceHolder.class);
private static ThreadLocal<String> contextHolder=new ThreadLocal<String>();//保证线程安全
public static final String DB_MASTER="master";
public static final String DB_SLAVE="slave";
public static String getDbType(){
String db=contextHolder.get();
if(db==null){
db=DB_MASTER;
}
return db;
}
public static void setDbType(String str){
logger.debug("所使用的数据源为:"+str);
contextHolder.set(str);
}
//清理连接类型
public static void clearDBType(){
contextHolder.remove();
} }

  

import java.util.Locale;
import java.util.Properties;
import java.util.concurrent.Executor; import org.apache.ibatis.executor.keygen.SelectKeyGenerator;
import org.apache.ibatis.mapping.BoundSql;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.mapping.SqlCommandType;
import org.apache.ibatis.plugin.Interceptor;
import org.apache.ibatis.plugin.Invocation;
import org.apache.ibatis.plugin.Plugin;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.transaction.support.TransactionSynchronizationManager; /**
* @author wls
*
*/

@Intercepts({@Signature(type=Executor.class,method="update",args={MappedStatement.class,Object.class}),
@Signature(type=Executor.class,method="query",args={MappedStatement.class,Object.class,
RowBounds.class,ResultHandler.class})})

public class DynamicDataSourceInterceptor implements Interceptor{
private static Logger logger=LoggerFactory.getLogger(DynamicDataSourceInterceptor.class);
private static final String REGEX=
".*insert\\u0020.*|.*delete\\u0020.*|.8update\\u0020.*"; @Override
public Object intercept(Invocation invocation) throws Throwable {
//判断当前是不是事物
boolean synchronizatioinActive=TransactionSynchronizationManager.
isActualTransactionActive();
Object[] objects= invocation.getArgs();
MappedStatement ms=(MappedStatement)objects[0];
String lookupKey=DynamicDataSourceHolder.DB_MASTER;
if(synchronizatioinActive!=true){ //读方法
if(ms.getSqlCommandType().equals(SqlCommandType.SELECT)){
//SELECT_KEY为自增id查询主键SELECT LAST_INSERT_ID(),使用主库
if(ms.getId().contains(SelectKeyGenerator.SELECT_KEY_SUFFIX)){
lookupKey=DynamicDataSourceHolder.DB_MASTER;
}else{
BoundSql boundSql=ms.getSqlSource().getBoundSql(objects[1]);
String sql=boundSql.getSql().toLowerCase(Locale.CHINA).
replaceAll("[\\t\\n\\r]", " ");
if(sql.matches(REGEX)){
lookupKey=DynamicDataSourceHolder.DB_MASTER; //增删改
}else{
lookupKey=DynamicDataSourceHolder.DB_SLAVE; //查,从库
}
}
}
}
else{
lookupKey=DynamicDataSourceHolder.DB_MASTER;
}
logger.debug("设置方法[{}] use[{}]Strategy,SqlCommanType[{}]" ,ms.getId(),lookupKey,
ms.getSqlCommandType().name());;
DynamicDataSourceHolder.setDbType(lookupKey);
return invocation.proceed();
} @Override //返回封装好的对象
public Object plugin(Object target) {
// TODO Auto-generated method stub
if(target instanceof Executor){
return Plugin.wrap(target, this);
}else{
return target;
}
} @Override
public void setProperties(Properties arg0) {
// TODO Auto-generated method stub }
}

  配置:

mybatis配置:

<plugins>
<plugin interceptor="split.DynamicDataSourceInterceptor"></plugin>
</plugins>

  

Java Mybatis实现主从同步的更多相关文章

  1. RocketMQ 主从同步若干问题答疑

    目录 1.初识主从同步 2.提出问题 3.原理探究 3.1 RocketMQ主从读写分离机制 3.2 消息消费进度同步机制 4.总结 温馨提示:建议参考代码RocketMQ4.4版本,4.5版本引入了 ...

  2. windows下mysql 主从同步

    半路出家到Java,刚开始听说到说程序支持读写分离感觉特别高大上,也一直没接触 偶然的机会接触到了,就一定得记下来. 今天先讲讲数据库的主从同步,两个好处: 一是读写分离可以用上.比如 写操作就写到主 ...

  3. MySQL主从同步和读写分离的配置

    主服务器:192.168.1.126 从服务器:192.168.1.163 amoeba代理服务器:192.168.1.237 系统全部是CentOS 6.7 1.配置主从同步 1.1.修改主服务器( ...

  4. mysql主从同步+mycat读写分离+.NET程序连接mycat代理

    背景 最近新项目需要用到mysql数据库,并且由于数据量大的原因,故打算采用1主1从(主数据库负责增.删.改操作:从数据库负责查操作)的数据库架构,在实现主从之后还要实现读写分离的代理,在网上搜寻了很 ...

  5. 重启mysql主从同步mongodb(tungsten-replicator)

    1. 连接mysql mysql -uroot -p;(mysql从库) 输入数据库密码 2. 停止主同步 mysql> stop slave; 3. 清数据 将mongo库数据清空 4. 杀主 ...

  6. Redis主从同步分析(转)

    一.Redis主从同步原理 1.1 Redis主从同步的过程 配置好slave服务器连接的master后,slave会建立和master的连接,然后发送sync命令.无论是第一次同步建立的连接还是连接 ...

  7. mysql 主从同步-读写分离

    主从同步与读写分离测试 一.  实验环境(主从同步) Master                   centos 7.3              192.168.138.13 Slave     ...

  8. Redis主从同步分析

    一.Redis主从同步原理1.1 Redis主从同步的过程配置好slave服务器连接的master后,slave会建立和master的连接,然后发送sync命令.无论是第一次同步建立的连接还是连接断开 ...

  9. 这次一定要教会你搭建Redis集群和MySQL主从同步(非Docker)

    前言 一直都想自己动手搭建一个Redis集群和MySQL的主从同步,当然不是依靠Docker的一键部署(虽然现在企业开发用的最多的是这种方式),所以本文就算是一个教程类文章吧,但在动手搭建之前,会先聊 ...

随机推荐

  1. 【XSY2990】树 组合数学 容斥

    题目描述 同 Comb Avoiding Trees 不过只用求一项. \(n,k\leq {10}^7\) 题解 不难发现一棵 \(n\) 个叶子的树唯一对应了一个长度为 \(2n-2\) 的括号序 ...

  2. [Qualcomm]A Detailed History of Qualcomm 高通的前世今生

    https://www.semiwiki.com/forum/content/7353-detailed-history-qualcomm.html

  3. 清北学堂Day2

    算数基本定理: 1.整数及其相关 2.唯一分解定理 对于任意的大于1的正整数N,N一定能够分解成有限个质数的乘积,即 其中P1<P2<...<Pk,a1,a2,...,ak>= ...

  4. Luogu P2057 [SHOI2007]善意的投票

    题目链接 \(Click\) \(Here\) 考虑模型转换.变成文理分科二选一带收益模型,就一波带走了. 如果没有见过这个模型的话,这里讲的很详细. #include <bits/stdc++ ...

  5. 信号(1): signal

    1. 头文件#include <signal.h> 2. 功能设置某一信号的对应动作 3. 函数原型void (*signal(int signum,void(* handler)(int ...

  6. vegas 为盖斯

    vegas 为盖斯 S键 分割素材U键 分开视频和音频I键渲染开始O渲染结束 默认布局 为盖斯新建项目的参数 剪好后渲染 插入字幕

  7. vim与程序员

    所有的 Unix Like 系统都会内建 vi 文书编辑器,其他的文书编辑器则不一定会存在. 但是目前我们使用比较多的是 vim 编辑器. vim 具有程序编辑的能力,可以主动的以字体颜色辨别语法的正 ...

  8. pip换源安装

    pip install --index-url https://pypi.tuna.tsinghua.edu.cn/simple 要安装的 有些工具安装太慢, 换源安装一下, 速度一下子飞起

  9. CSS 书写规范

    class 类名的命名应该以功能为依据: 例如: .btn-danger;  .btn-warning CSS组件 一个组件==一个独立的功能模块 针对一个组件,通过功能描述样式   组件命名,功能描 ...

  10. js文件上传原理(form表单 ,FormData + XHR2 + FileReader + canvas)

    目录 form表单上传 FormData + XHR2 + FileReader + canvas 无刷新本地预览压缩上传实例 目前实现上传的方式 浏览器小于等于IE9(低版本浏览器)使用下面的方式实 ...