无论使用Spring JDBC, Hibernate还是Mybatis, 都需要Spring的datasource。 如果分布在三个远程机器上的数据库,拥有相同的数据库schema,唯一不同的只是其中的数据。 如何在Spring中可以动态的调整数据源呢?
最笨拙的穷举方法是配置三个datasource,然后为每一种datasource都配置自己的Dao。这种方法产生了大量的冗余。
Spring提供了一种方法,可以动态的调整datasource。使用AbstractRoutingDataSource做路由,根据环境参数而在不同的datasource之间切换。
public class RouterDataSouce extends AbstractRoutingDataSource {
/* (non-Javadoc)
* @see org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource#determineCurrentLookupKey()
*/
@Override
protected Object determineCurrentLookupKey() {
return Context.getEnv();
}
}
public class Context {
private static final ThreadLocal<String> env = new ThreadLocal<String>();
public static void setEnv(String e) {
env.set(e);
}
public static String getEnv() {
return env.get();
}
}
<bean id="dsBasic" class="org.apache.commons.dbcp2.BasicDataSource" destroy-method="close">
<property name="driverClassName" value="oracle.jdbc.driver.OracleDriver"></property>
<property name="initialSize" value="1"/>
<property name="maxTotal" value="5"/>
<property name="minIdle" value="1"/>
<property name="maxIdle" value="3"/>
<property name="maxWaitMillis" value="5000"/>
<property name="validationQuery" value="SELECT 1 FROM DUAL"/>
</bean>
<bean id="dsDev" parent="dsBasic">
<property name="url" value="jdbc:oracle:thin:@USALDBLXD009.luxgroup.net:1521:TVTXDEV"></property>
<property name="username" value="****"></property>
<property name="password" value="****"></property>
</bean>
<bean id="dsQa" parent="dsBasic">
<property name="url" value="jdbc:oracle:thin:@USALDBLXT017.luxgroup.net:1521:TVTXTST"></property>
<property name="username" value="****"></property>
<property name="password" value="****"></property>
</bean>
<bean id="dsPrd" parent="dsBasic">
<property name="url" value="jdbc:oracle:thin:@usswdblxp029.luxgroup.net:1521:TVTXPRD"></property>
<property name="username" value="****"></property>
<property name="password" value="****"></property>
</bean>
<bean id="dataSource" class="com.lux.ciao.rte.db.RouterDataSouce">
<property name="targetDataSources">
<map>
<entry key="dev" value-ref="dsDev"/>
<entry key="qa" value-ref="dsQa"/>
<entry key="prd" value-ref="dsPrd"/>
</map>
</property>
<property name="defaultTargetDataSource" ref="dsDev"/>
</bean>
ID为dataSource的bean为被外使用的数据源。但它只是一个路由器,它会根据determineCurrentLookupKey方法的返回值,来返回实际的数据源。
所以,在每个HTTP Request过来以后,可以使用Context中的setEnv方法来切换数据源。