<dependency>
<groupId>com.baomidou</groupId>
<artifactId>dynamic-datasource-spring-boot-starter</artifactId>
<version>3.5.1</version>
</dependency>
1、设置默认数据库
spring:
datasource:
dynamic:
strict: false #设置严格模式,默认false不启动,未匹配到指定数据源时会抛出异常并使用默认数据源.
primary: test_master
datasource:
test_master:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://127.0.0.1:3306/test_master?serverTimezone=GMT%2B8&useUnicode=true&characterEncoding=utf-8
username: root
password: 666666
jpa:
hibernate:
ddl-auto: update
database-platform: org.hibernate.dialect.MySQL5InnoDBDialect
show-sql: true
open-in-view: true
2、项目启动时将所有租户的数据源进行加载
测试数据库
/**
* {@link KunLunSourcesApplication } .
*
* @version v1.0
* @date 2024/7/5 0005
*/
@Component
@SpringBootApplication
@RequiredArgsConstructor
public class KunLunSourcesApplication implements ApplicationRunner {
private final DataSource dataSource;
private final DefaultDataSourceCreator dataSourceCreator;
private final DataSourceRepository dataSourceRepository;
public static void main(String[] args) {
SpringApplication.run(KunLunSourcesApplication.class, args);
}
@Override
public void run(ApplicationArguments args) throws Exception {
dataSourceRepository.findAll().forEach(dataSourceDO -> {
DataSourceProperty dataSourceProperty = new DataSourceProperty();
dataSourceProperty.setDriverClassName(dataSourceDO.getDataSourceDriver());
dataSourceProperty.setPassword(dataSourceDO.getDataSourcePassword());
dataSourceProperty.setUsername(dataSourceDO.getDataSourceAccount());
dataSourceProperty.setUrl(dataSourceDO.getDataSourceUrl());
DynamicRoutingDataSource ds = (DynamicRoutingDataSource) dataSource;
DataSource dataSource = dataSourceCreator.createDataSource(dataSourceProperty);
ds.addDataSource(dataSourceDO.getTenantName(), dataSource);
});
}
}
加载成功
3、编辑拦截器进行切换数据库
public class DatasourceSwitching implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
//从请求头部中中获取到token
String poolName = request.getHeader("tenant");
DynamicDataSourceContextHolder.clear();
//切换到对应poolName的数据源
DynamicDataSourceContextHolder.push(poolName);
return true;
}
}
@Configuration
public class DatasourceInterceptor implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new DatasourceSwitching()).addPathPatterns("/api/**");
}
}
注意:切换数据库的地方,不能用事务@Transactional(rollbackOn = Exception.class),否则不能正常切换数据库,好像是事务冲突导致,没仔细研究原因。