之前编写 多数据源配置 时,那是要多坑有多坑
Spring动态配置多数据源,即在大型应用中对数据进行切分,并且采用多个数据库实例进行管理,这样可以有效提高系统的水平伸缩性。而这样的方案就会不同于常见的单一数据实例的方案,这就要程序在运行时根据当时的请求及系统状态来动态的决定将数据存储在哪个数据库实例中,以及从哪个数据库提取数据。
Spring-context.xml 配置
数据连接 dataSource1 dataSource2
<bean id="dataSource1" class="com.alibaba.druid.pool.DruidDataSource">
<property name="driverClassName" value="${jdbc.driver}" />
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}" />
<property name="initialSize" value="1" />
<property name="minIdle" value="1" />
<property name="maxActive" value="20" />
<!-- 配置获取连接等待超时的时间 -->
<property name="maxWait" value="30000" />
<!-- 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒 -->
<property name="timeBetweenEvictionRunsMillis" value="60000" />
<!-- 配置一个连接在池中最小生存的时间,单位是毫秒 -->
<property name="minEvictableIdleTimeMillis" value="300000" />
<property name="testWhileIdle" value="true" />
<!-- 这里建议配置为TRUE,防止取到的连接不可用 -->
<property name="testOnBorrow" value="true" />
<property name="testOnReturn" value="false" />
<!-- 打开PSCache,并且指定每个连接上PSCache的大小 -->
<property name="poolPreparedStatements" value="false" />
<!-- 验证连接有效与否的SQL,不同的数据配置不同 -->
<property name="validationQuery" value="select 1 " />
</bean>
<bean id="dataSource2" class="com.alibaba.druid.pool.DruidDataSource">
<property name="driverClassName" value="${jdbc.driver}" />
<property name="url" value="${jdbc.url2}"/>
<property name="username" value="${jdbc.username2}"/>
<property name="password" value="${jdbc.password2}" />
<property name="initialSize" value="1" />
<property name="minIdle" value="1" />
<property name="maxActive" value="20" />
<!-- 配置获取连接等待超时的时间 -->
<property name="maxWait" value="30000" />
<!-- 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒 -->
<property name="timeBetweenEvictionRunsMillis" value="60000" />
<!-- 配置一个连接在池中最小生存的时间,单位是毫秒 -->
<property name="minEvictableIdleTimeMillis" value="300000" />
<property name="testWhileIdle" value="true" />
<!-- 这里建议配置为TRUE,防止取到的连接不可用 -->
<property name="testOnBorrow" value="true" />
<property name="testOnReturn" value="false" />
<!-- 打开PSCache,并且指定每个连接上PSCache的大小 -->
<property name="poolPreparedStatements" value="false" />
<!-- 验证连接有效与否的SQL,不同的数据配置不同 -->
<property name="validationQuery" value="select 1 " />
</bean>
<!-- 动态配置数据源 -->
<bean class="com.parts.utls.DynamicDataSource" id="dynamicDataSource">
<property name="targetDataSources">
<map key-type="java.lang.String">
<!--通过不同的key决定用哪个dataSource-->
<entry key="dataSource1" value-ref="dataSource1" />
<entry key="dataSource2" value-ref="dataSource2" />
</map>
</property>
<!--设置默认的dataSource-->
<property name="defaultTargetDataSource" ref="dataSource1"/>
</bean>
<bean id="sqlSessionFactory"class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dynamicDataSource" />
<property name="configLocation" value="classpath:spring-mybatis.xml" />
<property name="mapperLocations" value="classpath:/mapping/*.xml" />
</bean>
.properties 文件 数据连接
jdbc.driver =com.microsoft.sqlserver.jdbc.SQLServerDriver
jdbc.url=jdbc:sqlserver://localhost:1433;databaseName=数据库
jdbc.username=sa
jdbc.password= 123``
``jdbc.url2=jdbc:sqlserver://localhost:1433;databaseName=数据库
jdbc.username2=sa
jdbc.password2= 123 ``
切换数据库工具类
import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;
/**
* 动态切换数据库
*
* @author Administrator
*
*/
public class DynamicDataSource extends AbstractRoutingDataSource {
@Override
protected Object determineCurrentLookupKey() {
return DynamicDataSourceHolder. getDataSource();
}
}
/**
* 数据库切换工具类
* @author Administrator
*
*/
public class DynamicDataSourceHolder {
/**
* 注意:数据源标识保存在线程变量中,避免多线程操作数据源时互相干扰
*/
private static final ThreadLocal<String> contextHolder = new ThreadLocal<String>();
public static String getDataSource() {
return ((String)contextHolder .get());
}
public static void setDataSource(String dataSource) {
contextHolder .set(dataSource);
}
public static void clearDataSource() {
contextHolder .remove();
}
}
在impl包
KPISeriveIntakeMapper是 Dao或Mapper包下的
@Resource(name = "KPISeriveIntakeMapper")
@Autowired
private KPISeriveIntakeMapper kPISeriveIntakeMapper;
在 controller 包下
//切换数据库
DynamicDataSourceHolder.setDataSource("dataSource1");
int count = iPartsTransBiz.getPartsTransCount(startTime);
//切换数据库
DynamicDataSourceHolder.setDataSource("dataSource2");
// 数据显示
List<KPISeriveIntake> list = iKPISeriveIntakeBiz.getKPISeriveIntakeList(str);