Springboot-DynamicData
springboot 多个数据源的配置
解决问题, 一个springboot 项目操作多个数据库的数据
新建springboot项目 添加pom依赖
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>1.3.2</version>
</dependency>
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper-spring-boot-starter</artifactId>
<version>1.2.5</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.40</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.4</version>
</dependency>
新建 config 包添加配置项
- 新建枚举类多个数据源
public enum DatabaseTypeEnum {
PRIMARY("1"), USER("2");
private String code;
DatabaseTypeEnum(String code) {
this.code = code;
}
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
public static DatabaseTypeEnum getDatabaseTypeEnum(String code) {
for (DatabaseTypeEnum databaseTypeEnum : DatabaseTypeEnum.values()) {
if (databaseTypeEnum.getCode().equals(code)) {
return databaseTypeEnum;
}
}
return null;
}
}
- 新建 HikariConfig 类,添加数据源配置
import com.zaxxer.hikari.HikariDataSource;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
/**
* @author yyb
* @time 2019/3/27
*/
@Service
public class HikariConfig {
@Value("${spring.datasource.username}")
private String userName;
@Value("${spring.datasource.password}")
private String password;
@Value("${spring.datasource.driver-class-name}")
private String driverClassName;
@Value("${spring.datasource.min-idle}")
private Integer minIdle;
@Value("${spring.datasource.max-active}")
private Integer maxActive;
@Value("${spring.datasource.validation-query}")
private String validationQuery;
@Value("${spring.datasource.connection-timeout}")
private Integer connectionTimeout;
@Value("${spring.datasource.max-left-time}")
private Integer maxLeftTime;
@Value("${spring.datasource.validation-time-out}")
private Integer validationTimeout;
@Value("${spring.datasource.idle-time-out}")
private Integer idleTimeout;
@Value("${spring.datasource.connection-init-sql}")
private String connectionInitSql;
/**
* 配置Hikari数据连接池
*
* @param url 数据源
* @return 连接池对象
*/
public HikariDataSource getHikariDataSource(String url) {
com.zaxxer.hikari.HikariConfig config = new com.zaxxer.hikari.HikariConfig();
config.setMinimumIdle(minIdle);
config.setMaximumPoolSize(maxActive);
config.setConnectionTestQuery(validationQuery);
config.setJdbcUrl(url);
config.setUsername(userName);
config.setPassword(password);
config.setDriverClassName(driverClassName);
config.setConnectionTimeout(connectionTimeout);
config.setMaxLifetime(maxLeftTime);
config.setValidationTimeout(validationTimeout);
config.setConnectionInitSql(connectionInitSql);
return new HikariDataSource(config);
}
/**
* 用于两个库账号密码不一样的时候
*
* @param url
* @param userName
* @param passwod
* @return
*/
public HikariDataSource getHikariDataSource(String url, String userName, String passwod) {
com.zaxxer.hikari.HikariConfig config = new com.zaxxer.hikari.HikariConfig();
config.setMinimumIdle(minIdle);
config.setMaximumPoolSize(maxActive);
config.setConnectionTestQuery(validationQuery);
config.setJdbcUrl(url);
config.setUsername(userName);
config.setPassword(passwod);
config.setConnectionTimeout(connectionTimeout);
config.setDriverClassName(driverClassName);
config.setMaxLifetime(maxLeftTime);
config.setValidationTimeout(validationTimeout);
config.setConnectionInitSql(connectionInitSql);
return new HikariDataSource(config);
}
- 新建DynamicDataSourceConfig 类配置两个数据源
import cn.abel.enums.DatabaseTypeEnum;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import javax.sql.DataSource;
import java.util.HashMap;
import java.util.Map;
/**
* @author yyb
* @time 2019/3/27
*/
@Configuration
@MapperScan(basePackages = "cn.abel.dao")
public class DynamicDataSourceConfig {
@Value("${spring.datasource.primary.url}")
private String primaryUrl;
@Value("${spring.datasource.user.url}")
private String userUrl;
@Value("${mybatis.mapper-locations}")
private String resources;
//当两个数据库连接账号密码不一样时
// @Value("${spring.datasource.user.username}")
// private String userName;
// @Value("${spring.datasource.user.password}")
// private String password;
@Autowired
private HikariConfig hikariConfig;
@Primary
@Bean(name = "primaryDataSource")
public DataSource getPrimaryDataSource() {
return hikariConfig.getHikariDataSource(primaryUrl);
}
@Bean(name = "userDataSource")
public DataSource getUserDataSource() {
return hikariConfig.getHikariDataSource(userUrl);
}
//当两个数据库连接账号密码不一样时使用
// @Bean(name = "userDataSource")
// public DataSource getUserDataSource() {
// return hikariConfig.getHikariDataSource(userUrl, userName, password);
// }
@Bean("dynamicDataSource")
public DynamicDataSource dynamicDataSource(@Qualifier("primaryDataSource") DataSource primaryDataSource,
@Qualifier("userDataSource") DataSource miaoMoreDataSource) {
Map<Object, Object> targetDataSources = new HashMap<>();
targetDataSources.put(DatabaseTypeEnum.PRIMARY, primaryDataSource);
targetDataSources.put(DatabaseTypeEnum.USER, miaoMoreDataSource);
DynamicDataSource dataSource = new DynamicDataSource();
dataSource.setTargetDataSources(targetDataSources);// 该方法是AbstractRoutingDataSource的方法
dataSource.setDefaultTargetDataSource(primaryDataSource);// 默认的datasource设置为myTestDbDataSource
return dataSource;
}
/**
* 根据数据源创建SqlSessionFactory
*/
@Bean
public SqlSessionFactory sqlSessionFactory(@Qualifier("dynamicDataSource") DynamicDataSource dynamicDataSource) throws Exception {
SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
bean.setDataSource(dynamicDataSource);
bean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources(resources));
return bean.getObject();
}
}
- 新建 DynamicDataSourceContextHolder 数据源切换路由
import cn.abel.enums.DatabaseTypeEnum;
/**
* @author yyb
* @time 2019/3/27
*/
public class DynamicDataSourceContextHolder {
private static final ThreadLocal<DatabaseTypeEnum> contextHolder = new ThreadLocal<>();
public static void setDatabaseType(DatabaseTypeEnum type){
contextHolder.set(type);
}
public static DatabaseTypeEnum getDatabaseType(){
return contextHolder.get();
}
public static void resetDatabaseType() {
contextHolder.set(DatabaseTypeEnum.PRIMARY);
}
}
- 新建 DynamicDataSource 动态数据源
import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;
/**
* @author yyb
* @time 2019/3/27
*/
public class DynamicDataSource extends AbstractRoutingDataSource {
@Override
protected Object determineCurrentLookupKey() {
return DynamicDataSourceContextHolder.getDatabaseType();
}
}
使用
在service 层调用dao 层的时候,进行数据源切换操作
public List<News> getByMap(Map<String, Object> map) {
//重置数据源,切换为默认数据源
DynamicDataSourceContextHolder.resetDatabaseType();
return newsDao.getByMap(map);
}
在需要的地方切换第二个数据源
public User getById(Integer id){
//切换为配置第二数据源
DynamicDataSourceContextHolder.setDatabaseType(DatabaseTypeEnum.USER);
return userDao.getById(id);
}
完整代码:https://github.com/527515025/springBoot/tree/master/springboot-dynamicDataSource