• mysql读写分离配置,利用mybatis实现,解释为什么dynamicDataSource不行


    之前发布了mysql主从配置的博客,配置完成之后,那么我们肯定要拿主从来做点什么。

    我第一想到的就是mysql的读写分离,让读写分离之后可以大大的提供mysql的性能,比单纯用mysql主从做备份好很多。

    网上找了很多,但是配置确实差别不大,实现的方式也大同小异,但是需要指出的是,如果你和我一样使用的是mybatis的话需要注意一些问题。

    首先配置数据源

    <!-- 配置dbcp数据源 -->
        <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">  
            <property name="driverClassName" value="com.mysql.jdbc.Driver" />  
            <property name="url" value="jdbc:mysql://192.168.75.128:3306/xxxxxx" />  
            <property name="username" value="${jdbc.username}" />
            <property name="password" value="${jdbc.password}" />
        </bean>
        
        <bean id="dataSource2" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">  
            <property name="driverClassName" value="com.mysql.jdbc.Driver" />  
            <property name="url" value="jdbc:mysql://192.168.75.130:3306/xxxxxx" />  
            <property name="username" value="${jdbc.username}" />
            <property name="password" value="${jdbc.password}" />
        </bean>
        
        <bean id="dynamicDataSource" class="util.DynamicDataSource">  
            <property name="targetDataSources">  
                <map key-type="java.lang.String">  
                    <entry value-ref="dataSource" key="dataSource"></entry>  
                    <entry value-ref="dataSource2" key="dataSource2"></entry>  
                </map>  
            </property>  
            <property name="defaultTargetDataSource" ref="dataSource" >  
            </property>  
        </bean>

    然后是配置DynamicDataSource

    package util;
    
    import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;
    
    public class DynamicDataSource extends AbstractRoutingDataSource{
    
        @Override
        protected Object determineCurrentLookupKey() {
            return CustomerContextHolder.getCustomerType();
        }
    
    }

    然后配置CustomerContextHolder

    package util;
    
    public class CustomerContextHolder {
        public static final String DATA_SOURCE_A = "dataSource";  
        public static final String DATA_SOURCE_B = "dataSource2";  
        private static final ThreadLocal<String> contextHolder = new ThreadLocal<String>();  
        public static void setCustomerType(String customerType) {  
            contextHolder.set(customerType);  
        }  
        public static String getCustomerType() {  
            return contextHolder.get();  
        }  
        public static void clearCustomerType() {  
            contextHolder.remove();  
        } 
    }

    最后使用

    CustomerContextHolder.setCustomerType(CustomerContextHolder.DATA_SOURCE_A);和CustomerContextHolder.setCustomerType(CustomerContextHolder.DATA_SOURCE_B);

    改变数据源在dao实现层

    主要参考的是这个网址

    http://blog.csdn.net/alaahong/article/details/8707915

    结果发现不对,你会发现不管你怎么设置数据源,都永远只是访问了一个默认的,而没有访问另一个,为什么呢?

    后来我发现,原来是使用mybatis的关系

    mybatis首先有一个工厂

    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
            <property name="dataSource" ref="dataSource" />
        </bean>

    这个工厂需要配置固定的数据源

    然后这个工厂会产出sqlSessionTemplate
        <bean id="sqlSessionTemplate" class="org.mybatis.spring.SqlSessionTemplate">
            <constructor-arg name="sqlSessionFactory" ref="sqlSessionFactory" />
        </bean>

    而我们的dao实现层就是利用sqlSessionTemplate去执行的sql语句,然后我们的sqlSessionTemplate至始至终都没有改变过,所以永远使用的是同一个数据源。

    依据这个情况我做了一些修改

    <!-- 配置mybitasSqlSessionFactoryBean -->
        <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
            <property name="dataSource" ref="dataSource" />
        </bean>
       
        <!-- 配置SqlSessionTemplate -->
        <bean id="sqlSessionTemplate" class="org.mybatis.spring.SqlSessionTemplate">
            <constructor-arg name="sqlSessionFactory" ref="sqlSessionFactory" />
        </bean>


        <!-- 配置mybitasSqlSessionFactoryBean2 -->
        <bean id="sqlSessionFactory2" class="org.mybatis.spring.SqlSessionFactoryBean">
            <property name="dataSource" ref="dataSource2" />
        </bean>
       
        <!-- 配置SqlSessionTemplate2 -->
        <bean id="sqlSessionTemplate2" class="org.mybatis.spring.SqlSessionTemplate">
            <constructor-arg name="sqlSessionFactory" ref="sqlSessionFactory2" />
        </bean>

    配置了两个工厂,拥有不同的数据源。

    然后在dao的实现层注解了两个不同的工厂

    @Resource(name = "sqlSessionTemplate")
        private SqlSessionTemplate sqlSessionTemplate;

        @Resource(name = "sqlSessionTemplate2")
        private SqlSessionTemplate sqlSessionTemplate2;

    然后使用两个不同的工厂去调用读取和修改。

    然后就成功了。

    但是实际的项目中,如果你真的这么做,那么对于程序员来说很痛苦。

    他们必须在每个dao的实现层有这么两个对象。

    然后对于查询调用哪一个,然后对于修改调用那一个必须很清楚,不能出错。

    这样来说之前那个dynamicDataSource配置就没有什么用了。

    主要就是靠mybatis的两个工厂实现了读写的分离。

    所以对于这个问题,我还要寻找更好的解决方案。

  • 相关阅读:
    模式识别 第一章 概论
    高等代数9 欧几里得空间
    离散数学6 初等数论
    高等代数6 线性空间
    高等代数5 二次型
    GMOJ 6870. 【2020.11.17提高组模拟】ckw的树 (tree)
    1
    Virtual Tree 学习笔记
    [2020.11.14提高组模拟] 鬼渊传说(village)
    企业购置新车,各项费用会计入账以及案例分析
  • 原文地址:https://www.cnblogs.com/linkstar/p/6009037.html
Copyright © 2020-2023  润新知