版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/zt_fucker/article/details/73848742
SSM单数据源的话,默认的数据源是DruidDataSource中指定数据源;
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource"
init-method="init" destroy-method="close">
<property name="driverClassName">
<value>${jdbc_driverClassName}</value>
</property>
<property name="url">
<value>${jdbc_url}</value>
</property>
<property name="username">
<value>${jdbc_username}</value>
</property>
<property name="password">
<value>${jdbc_password}</value>
</property>
<!-- 连接池最大使用连接数 -->
<property name="maxActive">
<value>20</value>
</property>
<!-- 初始化连接大小 -->
<property name="initialSize">
<value>1</value>
</property>
<!-- 获取连接最大等待时间 -->
<property name="maxWait">
<value>60000</value>
</property>
<!-- 连接池最大空闲 -->
<property name="maxIdle">
<value>20</value>
</property>
<!-- 连接池最小空闲 -->
<property name="minIdle">
<value>3</value>
</property>
<!-- 自动清除无用连接 -->
<property name="removeAbandoned">
<value>true</value>
</property>
<!-- 清除无用连接的等待时间 -->
<property name="removeAbandonedTimeout">
<value>180</value>
</property>
<!-- 连接属性 -->
<property name="connectionProperties">
<value>clientEncoding=UTF-8</value>
</property>
</bean>
正常来讲,一个DataSource对应的是一个sqlSessionFactory,如果配置多数据源的话,对应的是多个sqlSessionFactory,管理和配置起来都非常费劲,为什么不设置一个动态变换数据源的方法呢?
答案是肯定的,在spring4的源码中写到:
/**
* Retrieve the current target DataSource. Determines the
* {@link #determineCurrentLookupKey() current lookup key}, performs
* a lookup in the {@link #setTargetDataSources targetDataSources} map,
* falls back to the specified
* {@link #setDefaultTargetDataSource default target DataSource} if necessary.
* @see #determineCurrentLookupKey()
* 检索当前目标数据源,通过determineCurrentLookupKey()方法确定当前的lookupkey,在数据源的map中执行一个lookup(通过setTargetDataSources()方法),如果没有的话回滚到默认的数据源。
*/
protected DataSource determineTargetDataSource() {
Assert.notNull(this.resolvedDataSources, "DataSource router not initialized");
Object lookupKey = determineCurrentLookupKey();
DataSource dataSource = this.resolvedDataSources.get(lookupKey);
if (dataSource == null && (this.lenientFallback || lookupKey == null)) {
dataSource = this.resolvedDefaultDataSource;
}
if (dataSource == null) {
throw new IllegalStateException("Cannot determine target DataSource for lookup key [" + lookupKey + "]");
}
return dataSource;
}
/**
* Determine the current lookup key. This will typically be
* implemented to check a thread-bound transaction context.
* <p>Allows for arbitrary keys. The returned key needs
* to match the stored lookup key type, as resolved by the
* {@link #resolveSpecifiedLookupKey} method.
* 确定当前的lookupkey。这通常是实现检查线程绑定的事务上下文,允许任意数量的key。返回的key需要匹配存储的key类型,通过resolveSpecifiedLookupKey()方法来解决。
*/
protected abstract Object determineCurrentLookupKey();
然后进行xml配置:
jdbc.properties
jdbc_driverClassName=com.mysql.jdbc.Driver
data01_jdbc_url=jdbc:mysql://172.16.14.40:3306/zhu?useUnicode=true&characterEncoding=utf-8&zeroDateTimeBehavior=convertToNull
data01_jdbc_username=zhu
data01_jdbc_password=zhu
jdbc_url=jdbc:mysql://172.16.14.52:3306/csca_manage?useUnicode=true&characterEncoding=utf-8&zeroDateTimeBehavior=convertToNull
jdbc_username=csca_manage
jdbc_password=csca_manage
spring_mybatis.xml
...
<bean id="dataSource01" class="com.alibaba.druid.pool.DruidDataSource"
init-method="init" destroy-method="close">
<property name="driverClassName">
<value>${jdbc_driverClassName}</value>
</property>
<property name="url">
<value>${data01_jdbc_url}</value>
</property>
<property name="username">
<value>${data01_jdbc_username}</value>
</property>
<property name="password">
<value>${data01_jdbc_password}</value>
</property>
</bean>
<!-- 配置datasource -->
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource"
init-method="init" destroy-method="close">
<property name="driverClassName">
<value>${jdbc_driverClassName}</value>
</property>
<property name="url">
<value>${jdbc_url}</value>
</property>
<property name="username">
<value>${jdbc_username}</value>
</property>
<property name="password">
<value>${jdbc_password}</value>
</property>
</bean>
<bean id="dynamicDataSource" class="com.guide.datasource.DynamicDataSource">
<property name="targetDataSources">
<map key-type="java.lang.String">
<!-- 指定lookupKey和与之对应的数据源 -->
<entry key="dataSource01" value-ref="dataSource01"></entry>
<entry key="dataSource" value-ref="dataSource"></entry>
</map>
</property>
<!-- 这里可以指定默认的数据源 -->
<property name="defaultTargetDataSource" ref="dataSource" />
</bean>
<!-- 需要注意的是,此处的dynamicDataSource为数据源的动态替代品,其他事物和sqlSessionFactory等注入的数据源也得进行相应的替换。 -->
...
DynamicDataSource.java
package com.guide.datasource;
import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;
public class DynamicDataSource extends AbstractRoutingDataSource {
@Override
protected Object determineCurrentLookupKey() {
// 从自定义的位置获取数据源标识
return DynamicDataSourceHolder.getDataSource();
}
}
DynamicDataSourceHolder.java
package com.guide.datasource;
public class DynamicDataSourceHolder {
/**
* 注意:数据源标识保存在线程变量中,避免多线程操作数据源时互相干扰
*/
private static final ThreadLocal<String> THREAD_DATA_SOURCE = new ThreadLocal<String>();
public static String getDataSource() {
return THREAD_DATA_SOURCE.get();
}
public static void setDataSource(String dataSource) {
THREAD_DATA_SOURCE.set(dataSource);
}
public static void clearDataSource() {
THREAD_DATA_SOURCE.remove();
}
}
使用的时候在实现类中:
public TUser query_ceshi() {
//切换数据源
DynamicDataSourceHolder.setDataSource(dataSource01);
return tUSerMapper.query_ceshi();
}
OK