Druid 可以说是国内使用最广泛的数据源连接池产品
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.1.17</version>
</dependency>
application.yml配置
spring:
datasource:
pay:
username: root
password: root
host: 192.168.37.133:3306
jdbc-url: jdbc:mysql://${spring.datasource.master.host}/${spring.datasource.master.schema-name}?useUnicode=true&characterEncoding=utf8&useSSL=false
schema-name: dlsms
order:
username: root
password: root
host: 192.168.37.134:3306
jdbc-url: jdbc:mysql://${spring.datasource.slave.host}/${spring.datasource.slave.schema-name}?useUnicode=true&characterEncoding=utf8&useSSL=false
schema-name: dlsms
配置数据源和事务管理
import net.test.project.constants.DataSourceKey;
import com.alibaba.druid.pool.DruidDataSource;
import java.util.HashMap;
import java.util.Map;
import javax.sql.DataSource;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.PlatformTransactionManager;
@MapperScan({"net.test.project.dao.mapper.*"})
@Configuration
public class DataSourceProxyConfig {
/**
* 配置默认数据源
* @return
*/
@Bean(name = "originOrder", initMethod = "init") // 声明其为Bean实例
@ConfigurationProperties(prefix = "spring.datasource.order")
public DataSource dataSourceMaster() {
return new DruidDataSource();
}
@Bean(name = "originStorage", initMethod = "init") // 声明其为Bean实例
@ConfigurationProperties(prefix = "spring.datasource.storage")
public DataSource dataSourceStorage() {
return new DruidDataSource();
}
@Bean(name = "originPay", initMethod = "init") // 声明其为Bean实例
@ConfigurationProperties(prefix = "spring.datasource.pay")
public DataSource dataSourcePay() {
return new DruidDataSource();
}
/**
* 设置多数据源,配置动态路由数据源
* @return
*/
@Bean("dynamicDataSource")
public DataSource dynamicDataSource(@Qualifier("originOrder") DataSource dataSourceOrder,
@Qualifier("originStorage") DataSource dataSourceStorage,
@Qualifier("originPay") DataSource dataSourcePay) {
DynamicDataSource dynamicRoutingDataSource = new DynamicDataSource();
Map<Object, Object> dataSourceMap = new HashMap<>(3);
dataSourceMap.put(DataSourceKey.ORDER.name(), dataSourceOrder);
dataSourceMap.put(DataSourceKey.STORAGE.name(), dataSourceStorage);
dataSourceMap.put(DataSourceKey.PAY.name(), dataSourcePay);
//设置默认
dynamicRoutingDataSource.setDefaultTargetDataSource(dataSourceOrder);
dynamicRoutingDataSource.setTargetDataSources(dataSourceMap);
return dynamicRoutingDataSource;
}
/**
* 设置会话工厂
*
* @return
* @throws Exception
*/
@Bean(name="sqlSessionFactory")
public SqlSessionFactoryBean sqlSessionFactoryBean(
@Qualifier("dynamicDataSource") DataSource dataSource) {
SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
sqlSessionFactoryBean.setDataSource(dataSource);
return sqlSessionFactoryBean;
}
/**
* 配置事务管理器
*
* @return
*/
@Bean(name = "transactionManager")
public PlatformTransactionManager transactionManager(@Qualifier("originOrder") DataSource dataSourceOrder,
@Qualifier("originStorage") DataSource dataSourceStorage,
@Qualifier("originPay") DataSource dataSourcePay) {
return new DataSourceTransactionManager(dynamicDataSource(dataSourceOrder, dataSourceStorage, dataSourcePay));
}
}
实现选择目标数据源
import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;
public class DynamicDataSource extends AbstractRoutingDataSource {
/**
* 取得当前使用哪个数据源
* @return
*/
@Override
protected Object determineCurrentLookupKey() {
return DynamicDataSourceContextHolder.getDataSourceType();
}
}
切换数据源
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* 数据源切换处理
*
*/
public class DynamicDataSourceContextHolder
{
public static final Logger log = LoggerFactory.getLogger(DynamicDataSourceContextHolder.class);
/**
* 使用ThreadLocal维护变量,ThreadLocal为每个使用该变量的线程提供独立的变量副本,
* 所以每一个线程都可以独立地改变自己的副本,而不会影响其它线程所对应的副本。
*/
private static final ThreadLocal<String> CONTEXT_HOLDER = new ThreadLocal<>();
/**
* 设置数据源的变量
*/
public static void setDataSourceType(String dsType)
{
log.info("切换到{}数据源", dsType);
CONTEXT_HOLDER.set(dsType);
}
/**
* 获得数据源的变量
*/
public static String getDataSourceType()
{
return CONTEXT_HOLDER.get();
}
/**
* 清空数据源变量
*/
public static void clearDataSourceType()
{
CONTEXT_HOLDER.remove();
}
}
如何使用
DynamicDataSourceContextHolder.setDataSourceType(DataSourceKey.ORDER);