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. vue 使用微信JSSDK,在IOS端会授权出错

    原因: vue-router切换的时候操作的都是浏览器的历史记录,iOS会把第一次刚进入时的URL作为真实URL,安卓会把当前URL作为真实URL. 所以导致后端在配置好的授权参数获得的config参 ...

  2. CMS Collector and G1 Collector

    Understanding the CMS Collector CMS has three basic operations: CMS collects the young generation (s ...

  3. CentOS 7安装MongoDB

    1 下载安装包 wget https://fastdl.mongodb.org/linux/mongodb-linux-x86_64-rhel70-3.2.4.tgz 2 解压 .tgz 3 将解压包 ...

  4. Android学习第十天

    计算机表示图形的几种方式 a)         Bmp:以高质量保存,用于计算机 b)         Jpg:以良好的质量保存,用于计算机或网络 c)         Png:以高质量保存 d)   ...

  5. [HackerRank]New Year Chaos[UNDONE]

    Input (stdin)Download 2 8 5 1 2 3 7 8 6 4 8 1 2 5 3 7 8 6 4 Your Output (stdout) Too chaotic Too cha ...

  6. Mybatis的应用2 使用mybits+SpringBoot完成第一个查询的demo(随后加增加,更新,删除)

    首先在mapper下面新建一个mysql.xml mysql.xml <?xml version="1.0" encoding="UTF-8" ?> ...

  7. 解决js复制在安卓和ios兼容问题

    var clipboard = new ClipboardJS('.fr', { // target: function() { // return document.querySelector('d ...

  8. 友盟冲突解决com.umeng.weixin.handler.UmengWXHandler cannot be cast to com.umeng.socialize.handler.UMWXHandler

    删掉一个试试

  9. halcon预处理函数

    颜色空间变换 trans_from_rgb(ImageRed, ImageGreen, ImageBlue :ImageResult1, ImageResult2, ImageResult3 : Co ...

  10. CMDB资产管理系统开发【day25】:windows客户端开发

    1.目录结构 PS Y:\MadkingClient> tree /f 卷 netgame 的文件夹 PATH 列表 卷序列号为 ACE3-896E Y:. ├─bin │ NedStark.p ...