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. 洛谷P3953逛公园

    题目 作为\(NOIp2017D1T3\) 这个题还是很良心的,至少相对于\(NOIp2018\)来说,希望\(NOIp2019\)不会这么坑吧. 这个题可以作为记忆化搜索的进阶题了,做这个题的方法也 ...

  2. [ZJOI2016]旅行者

    题目描述 小Y来到了一个新的城市旅行.她发现了这个城市的布局是网格状的,也就是有n条从东到西的道路和m条从南到北的道路,这些道路两两相交形成n*m个路口 (i,j)(1<=i<=n,1&l ...

  3. java实现sftp客户端上传文件夹的功能

    使用的jar: <dependencies> <dependency> <groupId>jsch</groupId> <artifactId&g ...

  4. Day046--JavaScript-- DOM操作, js中的面向对象, 定时

    一. DOM的操作(创建,追加,删除) parentNode 获取父级标签 nextElementSibling 获取下一个兄弟节点 children 获取所有的子标签 <!DOCTYPEhtm ...

  5. django系列7:修改404页面展示,优化模板,降低urlconf和模板之间的耦合,命名app将模板和app绑定

    为了增加程序的友好和健壮性,修改view代码,处理以下如果出现404,页面的UI展示. 修改view代码 from django.http import Http404 from django.sho ...

  6. IIC协议理解(转)

    目录 IIC协议理解(转) 个人小结记录 (记一下这个就够了) 以下为转载记录 概述 概述 输出级 主设备与从设备 速率 时序 空闲状态 起始位与停止位 数据的有效性 数据的传送 工作过程 主设备向从 ...

  7. linux 触摸屏驱动

    目录 linux 触摸屏驱动 输入子系统怎么写? 触摸屏事件 事件分类 事件设置 硬件配置 设计思路 完整程序 测试 ts_lib 使用 问题小结 title: linux 触摸屏驱动 tags: l ...

  8. Python中查看函数相关文档

    1.dir查看对象属性 >>> dir(set) ['__and__', '__class__', '__contains__', '__delattr__', '__dir__', ...

  9. SpringCloud笔记四:Ribbon

    目录 什么是Ribbon? Ribbon的配置 Maven引入 开启注解 Ribbon负载均衡 新建provider8002和8003 Ribbon核心组件IRule Ribbon自定义 什么是Rib ...

  10. C#中的Finalize,Dispose,SuppressFinalize的实现和使用介绍

    原文地址:http://www.csharpwin.com/csharpspace/8927r1397.shtml MSDN建议按照下面的模式实现IDisposable接口: public class ...