前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >mybatis plugins实现项目【全局】读写分离

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

作者头像
肖哥哥
发布2019-02-22 10:48:06
6370
发布2019-02-22 10:48:06
举报

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

注解实现读写分离: 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.首先定义数据源切换方法

代码语言:javascript
复制
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.继承抽象数据源接口并重写方法确定用哪一个数据源

代码语言:javascript
复制
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

代码语言:javascript
复制
<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常规配置外,其它部分配置是分表用的)

代码语言:javascript
复制
<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

代码语言:javascript
复制
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);
        }

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

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2016-09-15 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
数据库
云数据库为企业提供了完善的关系型数据库、非关系型数据库、分析型数据库和数据库生态工具。您可以通过产品选择和组合搭建,轻松实现高可靠、高可用性、高性能等数据库需求。云数据库服务也可大幅减少您的运维工作量,更专注于业务发展,让企业一站式享受数据上云及分布式架构的技术红利!
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档