专栏首页后台及大数据开发mybatis plugins实现项目【全局】读写分离

mybatis plugins实现项目【全局】读写分离

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

注解实现读写分离: 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);
        }

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

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • springBoot系列教程08:拦截器(Interceptor)的使用

    仔细阅读 过滤器(filter)和拦截器(interceptor)的区别 后明白了不少

    肖哥哥
  • springBoot系列教程04:mybatis及druid数据源的集成及查询缓存的使用

    首先说下查询缓存:查询缓存就是相同的数据库查询请求在设定的时间间隔内仅查询一次数据库并保存到redis中,后续的请求只要在时间间隔内都直接从redis中获取,不...

    肖哥哥
  • shiro权限管理框架与springmvc整合

    shiro是apache下的一个项目,和spring security类似,用于用户权限的管理‘

    肖哥哥
  • MyBatis 源代码阅读笔记 1 基于XML配置的代码编写 mybatis-config.xml

    MyBatis 是一款优秀的持久层框架,它支持定制化 SQL、存储过程以及高级映射。MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集...

    一个会写诗的程序员
  • Spring Boot入门系列(八)整合定时任务Task,一秒搞定定时任务

    今天主要讲解Springboot整合定时任务。在SpringMvc中也会用到很多的定时任务,主要是通过Quartz实现。但是在Spring MVC中使用这些插件...

    架构师精进
  • Mybatis自定义SQL拦截器

    本博客介绍的是继承Mybatis提供的Interface接口,自定义拦截器,然后将项目中的sql拦截一下,打印到控制台。

    SmileNicky
  • 《Spring Boot极简教程》第16章 Spring Boot安全集成Spring Security小结

    开发Web应用,对页面的安全控制通常是必须的。比如:对于没有访问权限的用户需要转到登录表单页面。要实现访问控制的方法多种多样,可以通过Aop、拦截器实现,也可以...

    一个会写诗的程序员
  • 8.6 Spring Boot集成Spring Security小结

    开发Web应用,对页面的安全控制通常是必须的。比如:对于没有访问权限的用户需要转到登录表单页面。要实现访问控制的方法多种多样,可以通过Aop、拦截器实现,也可以...

    一个会写诗的程序员
  • 使用ElasticSearch完成百万级数据查询附近的人功能

    上一篇文章介绍了ElasticSearch使用Repository和ElasticSearchTemplate完成构建复杂查询条件,简单介绍了ElasticSe...

    天涯泪小武
  • springCloud - 第3篇 - 消费者调用服务 ( RestTemplate + Ribbon )

    2. spring Initializr - module SDK 选择自己的 JDK ,其余的可以不用填写,next。

    微风-- 轻许--

扫码关注云+社区

领取腾讯云代金券