您的位置:首页 > 编程语言 > Java开发

Spring+Mybatis多数据源配置(四)——AbstractRoutingDataSource实现数据源动态切换

2017-03-10 22:51 471 查看
有时候需要在程序中动态切换数据源,那么这个系列的之前的博文所阐述的方法就不再使用了,总不能通过程序更改config.properties文件的dataSource的值,然后再重启web服务器以便加载applicationContext.xml文件。这里讲诉的是如何利用AbstractRoutingDataSource进行数据源动态切换。

首先上applicationContext.xml文件:

[html] view
plain copy

<?xml version="1.0" encoding="UTF-8" ?>  

<beans xmlns="http://www.springframework.org/schema/beans"  

        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  

        xmlns:context="http://www.springframework.org/schema/context"  

        xmlns:aop="http://www.springframework.org/schema/aop"   

        xmlns:tx="http://www.springframework.org/schema/tx"   

        xsi:schemaLocation="  

        http://www.springframework.org/schema/beans  

        classpath:/org/springframework/beans/factory/xml/spring-beans-3.0.xsd  

        http://www.springframework.org/schema/aop   

        classpath:/org/springframework/aop/config/spring-aop-3.0.xsd  

        http://www.springframework.org/schema/context  

        classpath:/org/springframework/context/config/spring-context-3.0.xsd  

        http://www.springframework.org/schema/tx   

        classpath:/org/springframework/transaction/config/spring-tx-3.0.xsd">  

  

    <!-- IoC配置 -->  

    <!-- 扫描类包,将标注Spring注解的类自动转化Bean,同时完成Bean的注入 -->  

    <context:component-scan base-package="com.shr.dao" />  

    <context:component-scan base-package="com.shr.service" />  

      

    <!-- DAO配置 -->  

    <context:property-placeholder location="classpath:config.properties"/>  

    <bean id="mysql" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">  

        <property name="driverClassName"     value="${mysql_driver}"/>  

        <property name="url"         value="${mysql_url}"/>  

        <property name="username"    value="${mysql_username}"/>  

        <property name="password"    value="${mysql_password}"/>  

    </bean>  

    <bean id="oracle" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">  

        <property name="driverClassName"     value="${ora_driver}"/>  

        <property name="url"         value="${ora_url}"/>  

        <property name="username"    value="${ora_username}"/>  

        <property name="password"    value="${ora_password}"/>  

    </bean>  

      

    <bean id="dataSource" class="com.shr.dao.datasource.DataSources">  

        <property name="targetDataSources">  

            <map key-type="java.lang.String">  

                <entry value-ref="mysql" key="MYSQL"></entry>  

                <entry value-ref="oracle" key="ORACLE"></entry>  

            </map>  

        </property>  

        <property name="defaultTargetDataSource" ref="mysql"></property>  

    </bean>  

  

    <bean id="vendorProperties"  

        class="org.springframework.beans.factory.config.PropertiesFactoryBean">  

        <property name="properties">  

            <props>  

                <prop key="Oracle">oracle</prop>  

                <prop key="MySQL">mysql</prop>  

            </props>  

        </property>  

    </bean>  

  

    <bean id="databaseIdProvider" class="org.apache.ibatis.mapping.VendorDatabaseIdProvider">  

        <property name="properties" ref="vendorProperties" />  

    </bean>  

    <bean name="myBatisSQLInterceptor" class="com.shr.dao.MyBatisSQLInterceptor"></bean>  

    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">  

        <property name="dataSource" ref="dataSource" />  

        <property name="typeAliasesPackage" value="com.shr.dao.pojo,com.shr.dao.model" />  

        <property name="databaseIdProvider" ref="databaseIdProvider" />  

        <property name="mapperLocations">  

            <list>  

                <value>classpath:com/shr/dao/resources/mappers/*_mapper.xml</value>  

            </list>  

        </property>  

        <!-- <property name="configLocation" value="/WEB-INF/mybatis-config.xml"/> -->  

        <property name="typeHandlersPackage" value="com.shr.dao" />  

        <property name="plugins">  

            <list>  

                <ref bean="myBatisSQLInterceptor"/>  

            </list>  

        </property>  

    </bean>  

      

    <!-- 配置事务管理器 -->  

    <tx:annotation-driven/>  

    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">  

        <property name="dataSource" ref="${dataSource}"/>  

    </bean>  

      

    <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">  

        <property name="basePackage" value="com.shr.dao.mapper"/>  

        <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/>   

        <!-- <property name="markerInterface" value="com.shr.dao.mapper.ITemplateMapper"/> -->  

    </bean>  

</beans>  

我们可以观察到文件中多了一段:

[html] view
plain copy

<bean id="dataSource" class="com.shr.dao.datasource.DataSources">  

    <property name="targetDataSources">  

        <map key-type="java.lang.String">  

            <entry value-ref="mysql" key="MYSQL"></entry>  

            <entry value-ref="oracle" key="ORACLE"></entry>  

        </map>  

    </property>  

    <property name="defaultTargetDataSource" ref="mysql"></property>  

</bean>  

而且sqlSessionFactory的dataSource是关联到上面这段内容的,而不是通过${dataSource}读取config.properties文件的内容获取的。

这个com.shr.dao.datasource.DataSources是自定义的类,继承自AbstractRoutingDataSource类,实现其determineCurrentLookupKey()方法。

代码如下:

[java] view
plain copy

package com.shr.dao.datasource;  

import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;  

public class DataSources extends AbstractRoutingDataSource  

{  

    @Override  

    protected Object determineCurrentLookupKey()  

    {  

        return DataSourceSwitch.getDataSourceType();  

    }  

}  

[java] view
plain copy

package com.shr.dao.datasource;  

  

public class DataSourceSwitch  

{  

    private static final ThreadLocal<String> contextHolder = new ThreadLocal<String>();  

      

    public static void setDataSourceType(String dataSourceType)  

    {  

        contextHolder.set(dataSourceType);  

    }  

      

    public static String getDataSourceType()  

    {  

        return contextHolder.get();  

    }  

      

    public static void clearDataSourceType()  

    {  

        contextHolder.remove();  

    }  

}  

[java] view
plain copy

package com.shr.dao.datasource;  

  

public class DataSourceInstances  

{  

    public static final String MYSQL="MYSQL";  

    public static final String ORACLE="ORACLE";  

}  

同样,我们通过一个junit测试用例进行验证:

[java] view
plain copy

package com.shr.dao.datasource;  

  

import java.util.List;  

  

import javax.inject.Inject;  

  

import org.junit.Test;  

import org.junit.runner.RunWith;  

import org.springframework.test.context.ContextConfiguration;  

import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;  

import org.springframework.test.context.transaction.TransactionConfiguration;  

import org.springframework.transaction.annotation.Transactional;  

  

import com.shr.dao.datasource.DataSourceInstances;  

import com.shr.dao.datasource.DataSourceSwitch;  

import com.shr.dao.model.userManage.UserListInfo;  

import com.shr.service.userManage.UserManageService;  

  

@RunWith(SpringJUnit4ClassRunner.class)  

@ContextConfiguration("file:WebContent/WEB-INF/applicationContext.xml")  

@Transactional  

@TransactionConfiguration(transactionManager="transactionManager",defaultRollback=false)  

public class DynamicDataSourceTest  

{  

    @Inject  

    private UserManageService userManageService;  

      

    @Test  

    public void test()  

    {  

        DataSourceSwitch.setDataSourceType(DataSourceInstances.MYSQL);  

        List<UserListInfo> list = userManageService.getUserListInfo();  

        for(UserListInfo user : list)  

        {  

            System.out.println(user.getUser_name());  

        }  

    }  

}  

通过改变DataSourceSwitch.setDataSourceType(DataSourceInstances.ORACLE);可以转换不同的数据源.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: