需求来源
实现代码生成器的时候因为做了分库,所以在实现代码生成时就需要根据不同的配置去拉取不同的表结构,所以需要实现不同的库使用不同的数据源
实现思路
在mybatis中是以DataSource的形式来管理数据源的,在mybaitis-plus中预留了AbstractRoutingDataSource接口来实现数据源的切换与查找

targetDataSources就是数据源的结合,如果我们需要增加数据源就需要在targetDataSources中增加新定义的数据源,并通知引用规则,实现如下
代码
首先我们要定义一个节点用于确定使用targetDataSources中的哪个数据源,定义DataSourceContextHolder,用于实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| public class DataSourceContextHolder { private static final ThreadLocal<String> contextHolder = new ThreadLocal<>(); public static void setDataSourceKey(String dataSourceKey) { contextHolder.set(dataSourceKey); } public static String getDataSourceKey() { return contextHolder.get(); } public static void clearDataSourceKey() { contextHolder.remove(); } }
|
定义DynamicDataSource继承与AbstractRoutingDataSource
1 2 3 4 5 6 7 8 9 10
| public DynamicDataSource(DataSource defaultDataSource, Map<Object, Object> targetDataSources) { // 设置数据源集合 super.setTargetDataSources(targetDataSources); super.setDefaultTargetDataSource(defaultDataSource); } @Override protected Object determineCurrentLookupKey() { return DataSourceContextHolder.getDataSourceKey(); }
|
这里只做了两件事定义数据源,以及确认当前数据源的key
定义一个Configuration
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| @Configuration @EnableConfigurationProperties(DataSourceProperties.class) public class PomeloDataSourceConfiguration { @Resource private DataSourceProperties dataSourceProperties; private DataSource defaultDataSource() { DataSource dataSource = DataSourceBuilder.create() .url(dataSourceProperties.getUrl()) .username(dataSourceProperties.getUsername()) .password(dataSourceProperties.getPassword()) .driverClassName(dataSourceProperties.getDriverClassName()) .build();; return dataSource; } @Bean @Primary public DynamicDataSource dynamicDataSource() { DynamicDataSource dynamicDataSource = new DynamicDataSource(defaultDataSource(), new HashMap<>()); return dynamicDataSource; }
|
如果我们需要使用多个数据源那需要我们获取到多个数据源,我们这里以数据库获取为例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| @Configuration public class DatasourceConfig { @Resource private GenDatabaseService genDatabaseService; @Resource private DynamicDataSource dynamicDataSource; @Bean public DynamicDataSource dataSourceInit() { // 创建数据源 Map<Object, Object> targetDataSources = new HashMap<>(); List<GenDatabase> genDatabaseList = genDatabaseService.selectList(); for (GenDatabase genDatabase : genDatabaseList) { targetDataSources.put(genDatabase.getDatabaseId().toString(), DataSourceBuilder.create() .driverClassName(genDatabase.getDatabaseDriver()) .url(genDatabase.getDatabaseUrl()) .password(genDatabase.getDatabasePwd()) .username(genDatabase.getDatabaseName()).build()); } dynamicDataSource.setTargetDataSources(targetDataSources); dynamicDataSource.afterPropertiesSet(); return dynamicDataSource; } }
|
这时如果需要再不同的地方调用数据源可以根据 DataSourceContextHolder.setDataSourceKey来确认使用哪个数据源,如果有需要也可以以aop形式完成,这里不多赘述
1 2
| DataSourceContextHolder.setDataSourceKey(tableQuery.getDatabaseId()); DataSourceContextHolder.clearDataSourceKey();
|