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的兩個工廠實現了讀寫的分離。

 

所以對於這個問題,我還要尋找更好的解決方案。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM