之前發布了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的兩個工廠實現了讀寫的分離。
所以對於這個問題,我還要尋找更好的解決方案。
