• 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);
            }

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

  • 相关阅读:
    web应用本质
    SQL逻辑查询语句执行顺序
    flask-WTForms组件
    生产者消费者模型
    单例模式
    flask中的信号量
    flask-script
    flask-session
    在python项目中导出项目依赖的模块信息
    Flask简介之简单应用
  • 原文地址:https://www.cnblogs.com/xiaochangwei/p/5875438.html
Copyright © 2020-2023  润新知