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

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

首先上applicationContext.xml文件:

<?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>

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

	<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()方法。

代码如下:

package com.shr.dao.datasource;
import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;
public class DataSources extends AbstractRoutingDataSource
{
	@Override
	protected Object determineCurrentLookupKey()
	{
		return DataSourceSwitch.getDataSourceType();
	}
}
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();
	}
}
package com.shr.dao.datasource;

public class DataSourceInstances
{
	public static final String MYSQL="MYSQL";
	public static final String ORACLE="ORACLE";
}

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

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);可以转换不同的数据源.

时间: 2024-09-30 01:15:31

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

项目重构之数据源配置与优化:log4j 配置数据库连接池Druid,并实现日志存储到数据库

一. 前言   泥瓦匠又和大家见面了,最近两天我在Code Review , 顺便代码小小的Refactoring(重构)下.先了解这个项目吧,这次解决的是数据源配置优化.因为这web项目中配置数据源的地方很多.例如 JDBC要配置数据源,Mybatis要配置数据源,Quartz定时任务要配置数据源,还有Log4j存记录到数据库也要配置-   如题目,兴许大家的疑惑看了前面的说明会明白.这次给大家带来的 数据源配置与优化:log4j 配置数据库连接池Druid.   提纲: 二.准备知识 三.正

spring mybatis 的注解事务

首先要在 spring-mybatis的配置文件添加 事务支持,和事务annotation支持 注意:如果是mysql请使用innodb innodb 支持事务功能,myisam 不支持. <!-- transaction support--> <!-- PlatformTransactionMnager --> <bean id="txManager" class="org.springframework.jdbc.datasource.Dat

国际化-spring mvc4 动态切换语言不起作用

问题描述 spring mvc4 动态切换语言不起作用 我利用 SPRING4 MVC配置了动态切换语言,但是在页上点击中文.英文切换的时候不起作用.请高手看看 <?xml version=""1.0"" encoding=""UTF-8""?><beans xmlns=""http://www.springframework.org/schema/beans"" xm

spring mvc4 动态切换语言不起作用

问题描述 我利用SPRING4MVC配置了动态切换语言,但是在页上点击中文.英文切换的时候不起作用.请高手看看spring-servlet.xml配置文件:<?xmlversion="1.0"encoding="UTF-8"?><beansxmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSch

Spring+Mybatis多数据源配置(二)——databaseIdProvider的使用

 在上一篇同系列的博文中,讲到配置多数据源,然后根据config.properties配置不同的数据库,进行切换.而且需要根据不同的数据库,配置不同的mybatis sql映射配置文件,如下: <property name="mapperLocations"> <list> <value>classpath:com/shr/dao/resources/${dataSource}mappers/*_mapper.xml</value> &l

Spring+Mybatis多数据源配置(一)——MySQL与Oracle通过配置切换

在小型项目中,一般配置一个数据库,也就是一个mybatis数据源,但是有时候需要同时支持两种数据库,比如mysql和oracle. 最笨的方法就是配置两个spring配置文件,然后根据不同的部署,采用不同的配置文件,其实这两个配置文件可以合成一个配置文件,通过java的properties文件进行配置. 首先说明下配置单个数据库,也就是单个数据源的配置. 首先看一下spring的配置文件applicationContext.xml(这里采用的是spring+mybatis,所以有关数据库的及my

spring boot druid mybatis 多数据源 配置

spring boot 在配置时做了很多简化配置的设置,但是简化的配置往往已牺牲一定的定制化,比如在数据源的配置时,spring boot 只提供4种数据库连接池的配置,其中并不支持常用的druid 阅读spring boot DataSourceBuilder 的源码可以发现 spring boot 提供的4种数据源类型并不是我们想要的 private static final String[] DATA_SOURCE_TYPE_NAMES = new String[] { "org.apac

Spring+Mybatis多数据源配置(三)——Spring如何获取Properties文件的信息

严格来说,本博文所阐述的内容和这个系列来说,没有什么必要的关系,本博文的主题是:如何使用spring获取properties文件的信息.本博文所采用的用例都和这个系列有关,所以就放在这里讲了. 通过spring的配置(applicationContext.xml),如:<context:property-placeholder location="classpath:config.properties"/>(具体位置可以参考本系列的前两篇博文),这个就配置了spring自动

【JAVA秒会技术之随意切换数据库】Spring如何高效的配置多套数据源

 Spring如何高效的配置多套数据源     真正的开发中,难免要使用多个数据库,进行不同的切换.无论是为了实现"读写分离"也好,还是为了使用不同的数据库("MySQL"或"Oracle"或"SQLServer").传统的方法,是配置多套Spring配置文件与Mysql配置文件,不仅配置起来较为混乱,而且切换及对事物的管理,也很麻烦.下面,博主就介绍一种方法,帮助大家解决"Spring如何高效的配置多套数据源&qu