zoukankan      html  css  js  c++  java
  • 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);
            }

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

  • 相关阅读:
    动态规划01背包
    动态规划矩阵连乘
    分治法归并排序
    动态规划最长公共子序列
    贪心算法活动安排
    分治法二分查找
    vue 可拖拽可缩放 vuedraggableresizable 组件常用总结
    rifilter in python discussed in 3delight
    3delight linear work flow
    pixar stereo rendering doc
  • 原文地址:https://www.cnblogs.com/xiaochangwei/p/5875438.html
Copyright © 2011-2022 走看看