在之前的文章中讲述过数据库主从同步和通过注解来为部分方法切换数据源实现读写分离

注解实现读写分离: http://www.cnblogs.com/xiaochangwei/p/4961807.html

mysql主从同步: http://www.cnblogs.com/xiaochangwei/p/4824355.html

如果项目所有读操作和写操作操作不同的数据库,完全读写分离,那么可以简单的通过mybaits的plugins来实现

读写分离的实现数据源切换部分,完全依靠 org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource,这是spring提供的抽象数据源方法

1.首先定义数据源切换方法

package net.zicp.xiaochangwei.web.multipeDataSource;

/**
* @author 肖昌伟 E-mail:317409898@qq.com
* @version 创建时间:2016年6月23日 下午2:04:33
*
*/
public class DataSourceSwith {
private static final ThreadLocal<String> contextHolder = new ThreadLocal<String>();
public static final String UPDATE = "UPDATE";
public static final String QUERY = "QUERY"; public static void setDataSource(String dataSource) {
contextHolder.set(dataSource);
} public static String getDataSource() {
return (String) contextHolder.get();
} public static void clearDataSource() {
contextHolder.remove();
}
}

2.继承抽象数据源接口并重写方法确定用哪一个数据源

package net.zicp.xiaochangwei.web.multipeDataSource;

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

/**
* @author 肖昌伟 E-mail:317409898@qq.com
* @version 创建时间:2016年6月23日 下午2:04:01
*
*/
public class DataSources extends AbstractRoutingDataSource { @Override
protected Object determineCurrentLookupKey() {
return DataSourceSwith.getDataSource();
} }

3.配置数据源并指明数据源对应的key

<bean id="dataSource" class="net.zicp.xiaochangwei.web.multipeDataSource.DataSources">
<property name="targetDataSources">
<map key-type="java.lang.String">
<entry value-ref="dataSourceUpdate" key="UPDATE"></entry>
<entry value-ref="dataSourceQuery" key="QUERY"></entry>
</map>
</property>
<property name="defaultTargetDataSource" ref="dataSourceUpdate"></property>
</bean>

4.配置mybatis plugins(只看红色部分,除mybatis常规配置外,其它部分配置是分表用的)

<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="configLocation" value="classpath:mybatis/Configuration.xml" />
<!-- mapper配置路径 -->
<property name="mapperLocations">
<list>
<value>classpath:mybatis/*Mapper.xml</value>
</list>
</property>
<property name="plugins">
<array>
<bean class="net.zicp.xiaochangwei.web.interceptors.MybatisInterceptor">
<property name="shardTableName" value="t_feed_back"/>
</bean>
</array>
</property>
</bean>

5.实现mybatisInterceptor

package net.zicp.xiaochangwei.web.interceptors;

import java.lang.reflect.Method;
import java.util.Date;
import java.util.Properties;
import java.util.regex.Matcher;
import java.util.regex.Pattern; import net.zicp.xiaochangwei.web.multipeDataSource.DataSourceSwith;
import net.zicp.xiaochangwei.web.utils.DateUtils; import org.apache.ibatis.cache.CacheKey;
import org.apache.ibatis.executor.Executor;
import org.apache.ibatis.mapping.BoundSql;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.mapping.MappedStatement.Builder;
import org.apache.ibatis.mapping.SqlSource;
import org.apache.ibatis.plugin.Interceptor;
import org.apache.ibatis.plugin.Intercepts;
import org.apache.ibatis.plugin.Invocation;
import org.apache.ibatis.plugin.Plugin;
import org.apache.ibatis.plugin.Signature;
import org.apache.ibatis.reflection.DefaultReflectorFactory;
import org.apache.ibatis.reflection.MetaObject;
import org.apache.ibatis.reflection.ReflectorFactory;
import org.apache.ibatis.reflection.factory.DefaultObjectFactory;
import org.apache.ibatis.reflection.factory.ObjectFactory;
import org.apache.ibatis.reflection.wrapper.DefaultObjectWrapperFactory;
import org.apache.ibatis.reflection.wrapper.ObjectWrapperFactory;
import org.apache.ibatis.session.ResultHandler;
import org.apache.ibatis.session.RowBounds;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.InitializingBean; /**
* @author 肖昌伟 E-mail:317409898@qq.com
* @version 创建时间:2016年6月23日 上午9:04:47
*
*/
@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, CacheKey.class, BoundSql.class }),
@Signature(type = Executor.class, method = "query", args = { MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class }) })
public class MybatisInterceptor implements Interceptor, InitializingBean { @Override
public Object intercept(Invocation invocation) throws Throwable {
Method method = invocation.getMethod(); Object[] arguments = invocation.getArgs();
MappedStatement ms = (MappedStatement) arguments[MAPPED_STATEMENT_INDEX];
BoundSql boundSql = ms.getBoundSql(arguments[PARAMETER_INDEX]); log.info("对数据库执行:" + method.getName() + " 操作, sql为: "+ boundSql.getSql()); // 切换数据源
if ("query".equals(method.getName())) {
DataSourceSwith.setDataSource(DataSourceSwith.QUERY);
} else {
DataSourceSwith.setDataSource(DataSourceSwith.UPDATE);
}

配置两个不同的数据源试试看吧

mybatis plugins实现项目【全局】读写分离的更多相关文章

  1. Spring Boot + Mybatis 多数据源配置实现读写分离

    本文来自网易云社区 作者:王超 应用场景:项目中有一些报表统计与查询功能,对数据实时性要求不高,因此考虑对报表的统计与查询去操作slave db,减少对master的压力. 根据网上多份资料测试发现总 ...

  2. mybatis通过插件方式实现读写分离

    原理:通过自定义mybatis插件,拦截Executor的update和query方法,检查sql中有select就用读的库,其它的用写的库(如果有调用存储过程就另当别论了) @Intercepts( ...

  3. SpringMVC4+MyBatis+SQL Server2014实现读写分离

    前言 基于mybatis的AbstractRoutingDataSource和Interceptor用拦截器的方式实现读写分离,根据MappedStatement的boundsql,查询sql的sel ...

  4. J2EE 项目读写分离

    先回答下 1.为啥要读写分离? 大家都知道最初开始,一个项目对应一个数据库,基本是一对一的,但是由于后来用户及数据还有访问的急剧增多, 系统在数据的读写上出现了瓶颈,为了让提高效率,想读和写不相互影响 ...

  5. 基于Spring和Mybatis拦截器实现数据库操作读写分离

    首先需要配置好数据库的主从同步: 上一篇文章中有写到:https://www.cnblogs.com/xuyiqing/p/10647133.html 为什么要进行读写分离呢? 通常的Web应用大多数 ...

  6. Spring aop应用之实现数据库读写分离

    Spring加Mybatis实现MySQL数据库主从读写分离 ,实现的原理是配置了多套数据源,相应的sqlsessionfactory,transactionmanager和事务代理各配置了一套,如果 ...

  7. java 读写分离

    源码地址:http://git.oschina.net/xiaochangwei 先回答下 1.为啥要读写分离? 大家都知道最初开始,一个项目对应一个数据库,基本是一对一的,但是由于后来用户及数据还有 ...

  8. ShardingJdbc-分表;分库;分库分表;读写分离;一主多从+分表;一主多从+分库分表;公共表;数据脱敏;分布式事务

    目录 创建项目 分表 导包 表结构 Yml 分库 Yml Java 分库分表 数据库 Yml 读写分离 数据库 Yml 其他 只请求主库 读写分离判断逻辑代码 一主多从+分表 Yml 一主多从+分库分 ...

  9. Spring + Mybatis项目实现数据库读写分离

    主要思路:通过实现AbstractRoutingDataSource类来动态管理数据源,利用面向切面思维,每一次进入service方法前,选择数据源. 1.首先pom.xml中添加aspect依赖 & ...

随机推荐

  1. 十分钟介绍mobx与react

    原文地址:https://mobxjs.github.io/mobx/getting-started.html 写在前面:本人英语水平有限,主要是写给自己看的,若有哪位同学看到了有问题的地方,请为我指 ...

  2. JavaScript常见的五种数组去重的方式

    ▓▓▓▓▓▓ 大致介绍 JavaScript的数组去重问题在许多面试中都会遇到,现在做个总结 先来建立一个数组 var arr = [1,2,3,3,2,'我','我',34,'我的',NaN,NaN ...

  3. JavaScript自定义媒体播放器

    使用<audio>和<video>元素的play()和pause()方法,可以手工控制媒体文件的播放.组合使用属性.事件和这两个方法,很容易创建一个自定义的媒体播放器,如下面的 ...

  4. Android Notification 详解(一)——基本操作

    Android Notification 详解(一)--基本操作 版权声明:本文为博主原创文章,未经博主允许不得转载. 微博:厉圣杰 源码:AndroidDemo/Notification 文中如有纰 ...

  5. [C#] C# 知识回顾 - 特性 Attribute

    C# 知识回顾 - 特性 Attribute [博主]反骨仔 [原文地址]http://www.cnblogs.com/liqingwen/p/5911289.html 目录 特性简介 使用特性 特性 ...

  6. 简析服务端通过GT导入SHP至PG的方法

    文章版权由作者李晓晖和博客园共有,若转载请于明显处标明出处:http://www.cnblogs.com/naaoveGIS/ 1.背景 项目中需要在浏览器端直接上传SHP后服务端进行数据的自动入PG ...

  7. [原] KVM虚拟机网络闪断分析

    背景 公司云平台的机器时常会发生网络闪断,通常在10s-100s之间. 异常情况 VM出现问题时,表现出来的情况是外部监控系统无法访问,猜测可能是由于系统假死,OVS链路问题等等.但是在出现网络问题的 ...

  8. IL异常处理

    异常处理在程序中也算是比较重要的一部分了,IL异常处理在C#里面实现会用到一些新的方法 1.BeginExceptionBlock:异常块代码开始,相当于try,但是感觉又不太像 2.EndExcep ...

  9. Firebug中调试中的js脚本中中文内容显示为乱码

    Firebug中调试中的js脚本中中文内容显示为乱码 设置 页面 UFT-8 编码没用, 解决方法:点击 "Firebug"工具栏 中的"选项"---" ...

  10. Autofac 的点滴

    泛型类型的注册和使用 public interface IRepository<T> where T:class { } public interface ISchoolDetailRep ...