转:http://www.cnblogs.com/yuxuan/p/3396581.html
Spring动态配置多数据源,即在大型应用中对数据进行切分,并且采用多个数据库实例进行管理,这样可以有效提高系统的水平伸缩性。而这样的方案就会不同于常见的单一数据实例的方案,这就要程序在运行时根据当时的请求及系统状态来动态的决定将数据存储在哪个数据库实例中,以及从哪个数据库提取数据。
Spring配置多数据源的方式和具体使用过程。
Spring对于多数据源,以数据库表为参照,大体上可以分成两大类情况:
一是,表级上的跨数据库。即,对于不同的数据库却有相同的表(表名和表结构完全相同)。
二是,非表级上的跨数据库。即,多个数据源不存在相同的表。
Spring2.x的版本中采用Proxy模式,就是我们在方案中实现一个虚拟的数据源,并且用它来封装数据源选择逻辑,这样就可以有效地将数据源选择逻辑从Client中分离出来。Client提供选择所需的上下文(因为这是Client所知道的),由虚拟的DataSource根据Client提供的上下文来实现数据源的选择。
具体的实现就是,虚拟的DataSource仅需继承AbstractRoutingDataSource实现determineCurrentLookupKey()在其中封装数据源的选择逻辑。
在spring 中,一个很好用但是容易被忽略的,就是AbstractRoutingDataSource,它的一个作用就是可以根据用户发起的不同请求去转换不同的数据源,比如根据用户的不同地区语言选择不同的数据库
步骤如下:
一、动态配置多数据源
1. 数据源的名称常量类:
package com.login; public class DataSourceConst { public static final String Admin = "admin"; public static final String User = "user"; }
package com.login; public class DataSourceContextHolder { 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.login; import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource; public class DynamicDataSource extends AbstractRoutingDataSource { @Override protected Object determineCurrentLookupKey() { // TODO Auto-generated method stub return DataSourceContextHolder.getDataSourceType(); } }
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd"> <!-- spring 读取数据库配置文件 --> <bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"> <property name="location" value="classpath:jdbc.properties" /> </bean> <bean id="parentDataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close"> <property name="driverClass" value="${jdbc.driver}"></property> <property name="user" value="${jdbc.username}"></property> <property name="password" value="${jdbc.password}"></property> <property name="autoCommitOnClose" value="true"/> <property name="checkoutTimeout" value="${cpool.checkoutTimeout}"/> <property name="initialPoolSize" value="${cpool.initialPoolSize}"/> <property name="minPoolSize" value="${cpool.minPoolSize}"/> <property name="maxPoolSize" value="${cpool.maxPoolSize}"/> <property name="maxIdleTime" value="${cpool.maxIdleTime}"/> <property name="preferredTestQuery" value="${cpool.preferredTestQuery}"/> <property name="acquireIncrement" value="${cpool.acquireIncrement}"/> <property name="maxIdleTimeExcessConnections" value="${cpool.maxIdleTimeExcessConnections}"/> </bean> <bean id="adminDataSource" parent="parentDataSource"> <property name="jdbcUrl" value="${jdbc.url}"></property> </bean> <bean id="userDataSource" parent="parentDataSource"> <property name="jdbcUrl" value="${jdbc.url1}"></property> </bean> <bean id="dataSource" class="com.login.DynamicDataSource"> <property name="targetDataSources"> <map key-type="java.lang.String"> <entry value-ref="adminDataSource" key="admin"></entry> <entry value-ref="userDataSource" key="user"></entry> </map> </property> <property name="defaultTargetDataSource" ref="adminDataSource"></property> </bean> <!-- Spring提供的iBatis的SqlMap配置 --> <bean id="sqlMapClient" class="org.springframework.orm.ibatis.SqlMapClientFactoryBean"> <property name="configLocation" value="classpath:sqlMapConfig.xml" /> <property name="dataSource" ref="dataSource" /> </bean> </beans>
<bean name="loginDao" class="com.login.LoginDao"> <property name="sqlMapClient" ref="sqlMapClient"></property> </bean> <bean name="loginService" class="com.login.LoginService"> <property name="loginDao" ref="loginDao"></property> </bean>
BeanFactory beanFactory = (BeanFactory)(new ClassPathXmlApplicationContext("applicationContext.xml")); LoginDao loginDao = (LoginDao)beanFactory.getBean("loginDao"); DataSourceContextHolder.setDataSourceType(DataSourceConst.Admin); loginDao.getUserInfo(); DataSourceContextHolder.setDataSourceType(DataSourceConst.User); loginDao.getUserInfo();