Spring Boot项目通过接口 动态添加/删除 数据源,添加数据源之后,动态切换数据源,然后使用mybaties查询切换后的数据源的数据。
1.首先需要在数据库中创建数据源的信息表,表中信息存储数据库的连接信息。
#数据源信息表
DROP TABLE IF EXISTS `datasource_config`;
CREATE TABLE IF NOT EXISTS `datasource_config`
(
`id` bigint(13) NOT NULL AUTO_INCREMENT COMMENT '主键',
`host` varchar(255) NOT NULL COMMENT '数据库地址',
`port` int(6) NOT NULL COMMENT '数据库端口',
`username` varchar(100) NOT NULL COMMENT '数据库用户名',
`password` varchar(100) NOT NULL COMMENT '数据库密码',
`database` varchar(100) DEFAULT 0 COMMENT '数据库名称',
PRIMARY KEY (`id`)
) ENGINE = InnoDB
DEFAULT CHARSET = utf8 COMMENT ='数据源配置表';
2.主要代码
2.1 pom文件
pom文件需要添加切面信息的依赖和数据连接的依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
<dependency>
<groupId>tk.mybatis</groupId>
<artifactId>mapper-spring-boot-starter</artifactId>
<version>2.1.5</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
2.2基础配置类
DatasourceConfig,主要通过DataSourceBuilder去构建一个自己定义的数据源,将其放入Spring容器中
@Configuration
public class DatasourceConfiguration {
@Bean
@ConfigurationProperties(prefix = "spring.datasource")
public DataSource dataSource() {
DataSourceBuilder<?> dataSourceBuilder = DataSourceBuilder.create();
dataSourceBuilder.type(DynamicDataSource.class);
return dataSourceBuilder.build();
}
}
MybatisConfiguration主要是将上一步构建出来的数据源配置到Mybatis的 `SqlSessionFactory` 里
@Configuration
@MapperScan(basePackages = "data.cloud.datas.mapper", sqlSessionFactoryRef = "sqlSessionFactory")
public class MybatisConfiguration {
/**
* 创建会话工厂。
*
* @param dataSource 数据源
* @return 会话工厂
*/
@Bean(name = "sqlSessionFactory")
@SneakyThrows
public SqlSessionFactory getSqlSessionFactory(@Qualifier("dataSource") DataSource dataSource) throws Exception {
SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
bean.setDataSource(dataSource);
return bean.getObject();
}
}
2.3 动态数据源主要逻辑
DatasourceConfigContextHolder 主要用于绑定当前线程所使用的数据源id,通过ThreadLocal 保证同一线程不可被修改
public class DatasourceConfigContextHolder {
private static final ThreadLocal<Long> DATASOURCE_HOLDER = ThreadLocal.withInitial(() -> DatasourceHolder.DEFAULT_ID);
private static