first commit

This commit is contained in:
2023-06-13 21:41:02 +08:00
parent 27dd2c917a
commit c407eace59
19 changed files with 179 additions and 344 deletions

View File

@ -1,40 +1,27 @@
qiaoba: qiaoba:
file-upload-path: C:/${spring.application.name}/uploadPath/ file-upload-path: C:/${spring.application.name}/uploadPath/
datasource: dataSources:
master: - driver: com.mysql.cj.jdbc.Driver
driver: com.mysql.cj.jdbc.Driver url: jdbc:mysql://192.168.0.202:3306/${spring.application.name}?useUnicode=true&characterEncoding=utf-8&serverTimezone=Asia/Shanghai&nullCatalogMeansCurrent=true&allowMultiQueries=true
url: jdbc:mysql://localhost:3306/${spring.application.name}?useUnicode=true&characterEncoding=utf-8&serverTimezone=Asia/Shanghai&nullCatalogMeansCurrent=true&allowMultiQueries=true
username: root username: root
password: root password: Root123456789.
pool: #连接池初始化大小
init: 5 #连接池初始化大小 initial-size: 5
min: 10 #最小空闲连接 #最小空闲线程
max: 20 #最大连接数 min-idle: 10
slaves: #最大连接池数量
- driver: com.mysql.cj.jdbc.Driver max-active: 20
url: jdbc:mysql://121.5.136.69:3306/qiaoba-boot-1?useUnicode=true&characterEncoding=utf-8&serverTimezone=Asia/Shanghai&nullCatalogMeansCurrent=true&allowMultiQueries=true - driver: com.mysql.cj.jdbc.Driver
username: root url: jdbc:mysql://192.168.0.203:3306/${spring.application.name}?useUnicode=true&characterEncoding=utf-8&serverTimezone=Asia/Shanghai&nullCatalogMeansCurrent=true&allowMultiQueries=true
password: LpYN7LUoL?l0OSpR2 username: root
pool: password: Root123456789.
init: 5 #连接池初始化大小
min: 10 initial-size: 5
max: 20 #最小空闲线程数
weight: 2 #权重 默认 1 min-idle: 10
is-use: true #是否使用 默认 true #最大连接池数量
- driver: com.mysql.cj.jdbc.Driver max-active: 20
url: jdbc:mysql://127.0.0.1:3306/qiaoba-boot?useUnicode=true&characterEncoding=utf-8&serverTimezone=Asia/Shanghai&nullCatalogMeansCurrent=true&allowMultiQueries=true
username: root
password: root
pool:
init: 5
min: 10
max: 20
is-use: false # 不使用该库
# 连接测试query配置检测连接是否有效
connectionTestQuery: SELECT 1
# 多久检查一次连接的活性
keepaliveTime: 30000
mybatis-plus: mybatis-plus:
configuration: configuration:

View File

@ -1,35 +1,26 @@
qiaoba: qiaoba:
file-upload-path: /opt/${spring.application.name}/uploadPath/ file-upload-path: /opt/${spring.application.name}/uploadPath/
datasource: dataSources:
master: - driver: com.mysql.cj.jdbc.Driver
driver: com.mysql.cj.jdbc.Driver url: jdbc:mysql://192.168.0.202:3306/${spring.application.name}?useUnicode=true&characterEncoding=utf-8&serverTimezone=Asia/Shanghai&nullCatalogMeansCurrent=true&allowMultiQueries=true
url: jdbc:mysql://localhost:3306/qiaoba-boot?useUnicode=true&characterEncoding=utf-8&serverTimezone=Asia/Shanghai&nullCatalogMeansCurrent=true&allowMultiQueries=true
username: root username: root
password: root password: Root123456789.
pool: #连接池初始化大小
init: 5 #连接池初始化大小 initial-size: 5
min: 10 #最小空闲连接 #最小空闲线程
max: 20 #最大连接数 min-idle: 10
slaves: #最大连接池数量
- driver: com.mysql.cj.jdbc.Driver max-active: 20
url: jdbc:mysql://121.5.136.69:3306/qiaoba-boot-1?useUnicode=true&characterEncoding=utf-8&serverTimezone=Asia/Shanghai&nullCatalogMeansCurrent=true&allowMultiQueries=true - driver: com.mysql.cj.jdbc.Driver
username: root url: jdbc:mysql://192.168.0.203:3306/${spring.application.name}?useUnicode=true&characterEncoding=utf-8&serverTimezone=Asia/Shanghai&nullCatalogMeansCurrent=true&allowMultiQueries=true
password: LpYN7LUoL?l0OSpR2 username: root
pool: password: Root123456789.
init: 5 #连接池初始化大小
min: 10 initial-size: 5
max: 20 #最小空闲线程数
weight: 2 #权重 默认 1 min-idle: 10
is-use: true #是否使用 默认 true #最大连接池数量
- driver: com.mysql.cj.jdbc.Driver max-active: 20
url: jdbc:mysql://127.0.0.1:3306/qiaoba-boot?useUnicode=true&characterEncoding=utf-8&serverTimezone=Asia/Shanghai&nullCatalogMeansCurrent=true&allowMultiQueries=true
username: root
password: root
pool:
init: 5
min: 10
max: 20
is-use: false # 不使用该库
mybatis-plus: mybatis-plus:

View File

@ -1,6 +1,5 @@
package com.qiaoba.common.database.config; package com.qiaoba.common.database.config;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil; import cn.hutool.core.collection.CollUtil;
import com.alibaba.druid.pool.DruidDataSource; import com.alibaba.druid.pool.DruidDataSource;
import com.qiaoba.common.base.constants.TenantConstant; import com.qiaoba.common.base.constants.TenantConstant;
@ -8,12 +7,8 @@ import com.qiaoba.common.base.context.BaseContext;
import com.qiaoba.common.base.enums.BaseEnum; import com.qiaoba.common.base.enums.BaseEnum;
import com.qiaoba.common.database.constants.DynamicDatasourceConstant; import com.qiaoba.common.database.constants.DynamicDatasourceConstant;
import com.qiaoba.common.database.entity.DynamicDataSource; import com.qiaoba.common.database.entity.DynamicDataSource;
import com.qiaoba.common.database.properties.DefaultDataSourceProperties; import com.qiaoba.common.database.properties.DataSourceProperties;
import com.qiaoba.common.database.properties.MasterInfo;
import com.qiaoba.common.database.properties.PoolInfo;
import com.qiaoba.common.database.properties.SlaveInfo;
import com.qiaoba.common.database.service.DynamicDatasourceService; import com.qiaoba.common.database.service.DynamicDatasourceService;
import com.qiaoba.common.database.utils.JdbcUtil;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
@ -21,7 +16,10 @@ import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy; import javax.annotation.PreDestroy;
import javax.annotation.Resource; import javax.annotation.Resource;
import java.sql.SQLException; import java.sql.SQLException;
import java.util.*; import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
/** /**
@ -41,19 +39,19 @@ public class DynamicDataSourceConfig {
@Resource @Resource
private DynamicDataSourceContext dataSource; private DynamicDataSourceContext dataSource;
@Resource @Resource
private DefaultDataSourceProperties defaultDataSourceProperties; private DataSourceProperties dataSourceProperties;
@Resource @Resource
private DynamicDatasourceService dynamicDatasourceService; private DynamicDatasourceService dynamicDatasourceService;
/** /**
* 使用中的数据源 * 主要数据源
*/ */
public static Map<Object, Object> MASTER_SOURCE_MAP = new ConcurrentHashMap<>(); public static Map<Object, Object> PRIMARY_DATASOURCE_MAP = new ConcurrentHashMap<>();
/** /**
* 备用数据源 * 备用数据源-每次取0索引
*/ */
public static Map<String, List<SlaveInfo>> SLAVE_SOURCE_MAP = new ConcurrentHashMap<>(); public static Map<String, List<DynamicDataSource>> BACKUP_DATASOURCE_MAP = new ConcurrentHashMap<>();
/** /**
* 把DynamicDataSourceContext 纳入容器管理其他地方使用DynamicDataSourceConfig 类可以直接从容器取对象并调用freshDataSource方法 * 把DynamicDataSourceContext 纳入容器管理其他地方使用DynamicDataSourceConfig 类可以直接从容器取对象并调用freshDataSource方法
@ -67,72 +65,51 @@ public class DynamicDataSourceConfig {
} }
private void initDefault() { private void initDefault() {
MasterInfo master = defaultDataSourceProperties.getMaster(); List<DynamicDataSource> dataSources = dataSourceProperties.getDataSources();
List<SlaveInfo> slaves = defaultDataSourceProperties.getSlaves(); // 0索引作为主数据源
// 将主数据源使用 addPrimaryMap(DynamicDatasourceConstant.MASTER_PREFIX + TenantConstant.DEFAULT_TENANT_ID, buildDataSource(dataSources.get(0)));
addMasterMap(DynamicDatasourceConstant.MASTER_PREFIX + TenantConstant.DEFAULT_TENANT_ID, buildDataSource(master.getDriver(), master.getUrl(), master.getUsername(), master.getPassword(), master.getPool())); dataSources.remove(0);
dataSource.freshDataSource(MASTER_SOURCE_MAP); // 非0索引的备用
// 将从数据源备用 addBackupMap(TenantConstant.DEFAULT_TENANT_ID, dataSources);
if (CollUtil.isNotEmpty(slaves)) { // 刷新数据源
for (int i = 0; i < slaves.size(); i++) { dataSource.freshDataSource(PRIMARY_DATASOURCE_MAP);
if (!slaves.get(i).getIsUse()) {
slaves.remove(i);
}
}
if (CollUtil.isNotEmpty(slaves)) {
SLAVE_SOURCE_MAP.put(DynamicDatasourceConstant.SLAVE_PREFIX + TenantConstant.DEFAULT_TENANT_ID, slaves);
}
}
} }
private void initTenant() { private void initTenant() {
setDefaultSetting(); setDefaultSetting();
List<DynamicDataSource> dynamicDataSourceList = dynamicDatasourceService.loadAllTenantDatasource(); Map<String, List<DynamicDataSource>> tenantDatasource = dynamicDatasourceService.loadAllTenantDatasource();
for (DynamicDataSource dynamicDataSource : dynamicDataSourceList) { for (String tenantId : tenantDatasource.keySet()) {
// 将主数据源加载 List<DynamicDataSource> dataSources = tenantDatasource.get(tenantId);
if (BaseEnum.YES.getCode().equals(dynamicDataSource.getIsMaster())) { for (int i = 0; i < dataSources.size(); i++) {
addMasterMap(DynamicDatasourceConstant.MASTER_PREFIX + dynamicDataSource.getTenantId(), buildDataSource(dynamicDataSource.getDriver(), dynamicDataSource.getUrl(), dynamicDataSource.getUsername(), dynamicDataSource.getPassword(), new PoolInfo(dynamicDataSource.getInitCount(), dynamicDataSource.getMinCount(), dynamicDataSource.getMaxCount()))); DynamicDataSource dynamicDataSource = dataSources.get(i);
dataSource.freshDataSource(MASTER_SOURCE_MAP); if (BaseEnum.YES.getCode().equals(dynamicDataSource.getIsPrimary())) {
} addPrimaryMap(DynamicDatasourceConstant.MASTER_PREFIX + tenantId, buildDataSource(dataSources.get(i)));
// 将从数据源备用 // 去除主要数据源,剩下皆为备用数据源
else { dataSources.remove(i);
if (Objects.isNull(SLAVE_SOURCE_MAP.get(DynamicDatasourceConstant.MASTER_PREFIX + dynamicDataSource.getTenantId()))) {
List<SlaveInfo> slaves = new ArrayList<>();
slaves.add(datasourceToSlave(dynamicDataSource));
SLAVE_SOURCE_MAP.put(DynamicDatasourceConstant.MASTER_PREFIX + dynamicDataSource.getTenantId(), slaves);
} else {
List<SlaveInfo> slaves = SLAVE_SOURCE_MAP.get(DynamicDatasourceConstant.MASTER_PREFIX + dynamicDataSource.getTenantId());
slaves.add(datasourceToSlave(dynamicDataSource));
} }
} }
// 备用数据源
addBackupMap(tenantId, dataSources);
} }
BaseContext.clearAllHolder(); BaseContext.clearAllHolder();
} // 刷新数据源
dataSource.freshDataSource(PRIMARY_DATASOURCE_MAP);
public void addTenantDataSource(String tenantId, String driver, String url, String username, String password, PoolInfo poolInfo) {
addMasterMap(DynamicDatasourceConstant.MASTER_PREFIX + tenantId, buildDataSource(driver, url, username, password, poolInfo));
dataSource.freshDataSource(MASTER_SOURCE_MAP);
} }
public void deleteTenantDataSource(String tenantId) { public void deleteTenantDataSource(String tenantId) {
MASTER_SOURCE_MAP.remove(DynamicDatasourceConstant.MASTER_PREFIX + tenantId); PRIMARY_DATASOURCE_MAP.remove(DynamicDatasourceConstant.MASTER_PREFIX + tenantId);
dataSource.freshDataSource(MASTER_SOURCE_MAP); dataSource.freshDataSource(PRIMARY_DATASOURCE_MAP);
} }
private static Object buildDataSource(String driver, String url, String username, String password, PoolInfo poolInfo) { private static Object buildDataSource(DynamicDataSource dynamicDataSource) {
boolean flag = JdbcUtil.checkConnect(driver, url, username, password);
if (!flag) {
log.error("数据源: " + url + " , 连接失败,请检查!");
return null;
}
DruidDataSource dataSource = new DruidDataSource(); DruidDataSource dataSource = new DruidDataSource();
dataSource.setUrl(url); dataSource.setUrl(dynamicDataSource.getUrl());
dataSource.setUsername(username); dataSource.setUsername(dynamicDataSource.getUsername());
dataSource.setPassword(password); dataSource.setPassword(dynamicDataSource.getPassword());
dataSource.setDriverClassName(driver); dataSource.setDriverClassName(dynamicDataSource.getDriver());
dataSource.setInitialSize(poolInfo.getInit()); dataSource.setInitialSize(dynamicDataSource.getInitialSize());
dataSource.setMinIdle(poolInfo.getMin()); dataSource.setMinIdle(dynamicDataSource.getMinIdle());
dataSource.setMaxActive(poolInfo.getMax()); dataSource.setMaxActive(dynamicDataSource.getMaxActive());
try { try {
dataSource.init(); dataSource.init();
return dataSource; return dataSource;
@ -147,23 +124,28 @@ public class DynamicDataSourceConfig {
*/ */
@PreDestroy @PreDestroy
public void close() { public void close() {
Set<Map.Entry<Object, Object>> entries = MASTER_SOURCE_MAP.entrySet(); Set<Map.Entry<Object, Object>> entries = PRIMARY_DATASOURCE_MAP.entrySet();
for (Map.Entry<Object, Object> entry : entries) { for (Map.Entry<Object, Object> entry : entries) {
DruidDataSource dataSource = (DruidDataSource) entry.getValue(); DruidDataSource dataSource = (DruidDataSource) entry.getValue();
dataSource.close(); dataSource.close();
} }
} }
private void addMasterMap(String name, Object dataSource) { private void addPrimaryMap(String name, Object dataSource) {
if (Objects.nonNull(dataSource)) { if (Objects.nonNull(dataSource)) {
MASTER_SOURCE_MAP.put(name, dataSource); PRIMARY_DATASOURCE_MAP.put(name, dataSource);
} }
} }
private SlaveInfo datasourceToSlave(DynamicDataSource dynamicDataSource) { private void addBackupMap(String tenantId, List<DynamicDataSource> dataSources) {
SlaveInfo slaveInfo = BeanUtil.copyProperties(dynamicDataSource, SlaveInfo.class); if (CollUtil.isNotEmpty(dataSources)) {
slaveInfo.setPool(new PoolInfo(dynamicDataSource.getInitCount(), dynamicDataSource.getMinCount(), dynamicDataSource.getMaxCount())); BACKUP_DATASOURCE_MAP.put(tenantId, dataSources);
return slaveInfo; }
}
private void handleDataSources(String tenantId, List<DynamicDataSource> dataSources) {
} }
public void setDefaultSetting() { public void setDefaultSetting() {

View File

@ -10,7 +10,7 @@ import lombok.NoArgsConstructor;
* *
* @author ailanyin * @author ailanyin
* @version 1.0 * @version 1.0
* @date 2023-04-24 21:47:48 * @since 2023-06-13 20:24:31
*/ */
@Data @Data
@Builder @Builder
@ -24,9 +24,9 @@ public class DynamicDataSource {
private String tenantId; private String tenantId;
/** /**
* 主 * 主要数据源
*/ */
private String isMaster; private String isPrimary;
/** /**
* 数据库-url * 数据库-url
@ -51,16 +51,16 @@ public class DynamicDataSource {
/** /**
* 连接池-初始化大小 * 连接池-初始化大小
*/ */
private Integer initCount; private Integer initialSize;
/** /**
* 连接池-最小空闲数 * 连接池-最小空闲线程
*/ */
private Integer minCount; private Integer minIdle;
/** /**
* 连接池-最大连接 * 连接池-最大连接池数量
*/ */
private Integer maxCount; private Integer maxActive;
} }

View File

@ -2,7 +2,7 @@ package com.qiaoba.common.database.factories;
import com.qiaoba.common.database.config.DynamicDataSourceConfig; import com.qiaoba.common.database.config.DynamicDataSourceConfig;
import com.qiaoba.common.database.config.DynamicDataSourceContext; import com.qiaoba.common.database.config.DynamicDataSourceContext;
import com.qiaoba.common.database.properties.DefaultDataSourceProperties; import com.qiaoba.common.database.properties.DataSourceProperties;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
@ -27,8 +27,8 @@ public class DynamicDataSourceFactory {
} }
@Bean @Bean
public DefaultDataSourceProperties defaultDataSourceProperties() { public DataSourceProperties defaultDataSourceProperties() {
return new DefaultDataSourceProperties(); return new DataSourceProperties();
} }
} }

View File

@ -1,5 +1,6 @@
package com.qiaoba.common.database.properties; package com.qiaoba.common.database.properties;
import com.qiaoba.common.database.entity.DynamicDataSource;
import lombok.Data; import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.boot.context.properties.EnableConfigurationProperties;
@ -9,12 +10,11 @@ import java.util.List;
@Component @Component
@ConfigurationProperties(prefix = "qiaoba.datasource") @ConfigurationProperties(prefix = "qiaoba")
@Data @Data
@EnableConfigurationProperties @EnableConfigurationProperties
public class DefaultDataSourceProperties { public class DataSourceProperties {
private MasterInfo master; private List<DynamicDataSource> dataSources;
private List<SlaveInfo> slaves;
} }

View File

@ -1,19 +0,0 @@
package com.qiaoba.common.database.properties;
import lombok.Data;
/**
* 数据源-主库-信息
*
* @author ailanyin
* @version 1.0
* @since 2023-04-23 15:37:43
*/
@Data
public class MasterInfo {
private String driver;
private String url;
private String username;
private String password;
private PoolInfo pool;
}

View File

@ -1,33 +0,0 @@
package com.qiaoba.common.database.properties;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* 数据源连接池信息
*
* @author ailanyin
* @version 1.0
* @since 2023-04-23 15:37:43
*/
@Data
@NoArgsConstructor
@AllArgsConstructor
public class PoolInfo {
/**
* 初始连接数
*/
private Integer init;
/**
* 最小空闲数
*/
private Integer min;
/**
* 最大连接数
*/
private Integer max;
}

View File

@ -1,25 +0,0 @@
package com.qiaoba.common.database.properties;
import lombok.Data;
/**
* 数据源-从库-信息
*
* @author ailanyin
* @version 1.0
* @since 2023-04-23 15:37:43
*/
@Data
public class SlaveInfo {
private Boolean isUse = true;
private String driver;
private String url;
private String username;
private String password;
/**
* 权重
*/
private Integer weight = 1;
private PoolInfo pool;
}

View File

@ -3,6 +3,7 @@ package com.qiaoba.common.database.service;
import com.qiaoba.common.database.entity.DynamicDataSource; import com.qiaoba.common.database.entity.DynamicDataSource;
import java.util.List; import java.util.List;
import java.util.Map;
/** /**
* 动态数据源接口 * 动态数据源接口
@ -16,7 +17,7 @@ public interface DynamicDatasourceService {
/** /**
* 加载所有租户的数据源 * 加载所有租户的数据源
* *
* @return 数据源集合 * @return 数据源集合 key: tenantId | value: list
*/ */
List<DynamicDataSource> loadAllTenantDatasource(); Map<String, List<DynamicDataSource>> loadAllTenantDatasource();
} }

View File

@ -1,107 +1,45 @@
{ {
"groups": [ "groups": [],
{
"name": "qiaoba.datasource",
"type": "com.qiaoba.common.database.properties.DefaultDataSourceProperties",
"sourceType": "com.qiaoba.common.database.properties.DefaultDataSourceProperties"
}
],
"properties": [ "properties": [
{ {
"name": "qiaoba.datasource.master", "name": "qiaoba.dataSources",
"type": "com.qiaoba.common.database.properties.MasterInfo", "type": "java.util.List<com.qiaoba.common.database.entity.DynamicDataSource>",
"sourceType": "com.qiaoba.common.database.properties.DefaultDataSourceProperties" "sourceType": "com.qiaoba.common.database.properties.DataSourceProperties"
}, },
{ {
"name": "qiaoba.datasource.master.driver", "name": "qiaoba.datasources.driver",
"type": "java.lang.String", "type": "java.lang.String",
"sourceType": "com.qiaoba.common.database.properties.DefaultDataSourceProperties" "sourceType": "com.qiaoba.common.database.properties.DataSourceProperties"
}, },
{ {
"name": "qiaoba.datasource.master.url", "name": "qiaoba.datasources.url",
"type": "java.lang.String", "type": "java.lang.String",
"sourceType": "com.qiaoba.common.database.properties.DefaultDataSourceProperties" "sourceType": "com.qiaoba.common.database.properties.DataSourceProperties"
}, },
{ {
"name": "qiaoba.datasource.master.username", "name": "qiaoba.datasources.username",
"type": "java.lang.String", "type": "java.lang.String",
"sourceType": "com.qiaoba.common.database.properties.DefaultDataSourceProperties" "sourceType": "com.qiaoba.common.database.properties.DataSourceProperties"
}, },
{ {
"name": "qiaoba.datasource.master.password", "name": "qiaoba.datasources.password",
"type": "java.lang.String", "type": "java.lang.String",
"sourceType": "com.qiaoba.common.database.properties.DefaultDataSourceProperties" "sourceType": "com.qiaoba.common.database.properties.DataSourceProperties"
}, },
{ {
"name": "qiaoba.datasource.master.pool", "name": "qiaoba.datasources.initial-size",
"type": "com.qiaoba.common.database.properties.PoolInfo",
"sourceType": "com.qiaoba.common.database.properties.DefaultDataSourceProperties"
},
{
"name": "qiaoba.datasource.master.pool.init",
"type": "java.lang.Integer", "type": "java.lang.Integer",
"sourceType": "com.qiaoba.common.database.properties.DefaultDataSourceProperties" "sourceType": "com.qiaoba.common.database.properties.DataSourceProperties"
}, },
{ {
"name": "qiaoba.datasource.master.pool.min", "name": "qiaoba.datasources.min-idle",
"type": "java.lang.Integer", "type": "java.lang.Integer",
"sourceType": "com.qiaoba.common.database.properties.DefaultDataSourceProperties" "sourceType": "com.qiaoba.common.database.properties.DataSourceProperties"
}, },
{ {
"name": "qiaoba.datasource.master.pool.max", "name": "qiaoba.datasources.max-active",
"type": "java.lang.Integer", "type": "java.lang.Integer",
"sourceType": "com.qiaoba.common.database.properties.DefaultDataSourceProperties" "sourceType": "com.qiaoba.common.database.properties.DataSourceProperties"
},
{
"name": "qiaoba.datasource.slaves",
"type": "java.util.List<com.qiaoba.common.database.properties.SlaveInfo>",
"sourceType": "com.qiaoba.common.database.properties.DefaultDataSourceProperties"
},
{
"name": "qiaoba.datasource.slaves.url",
"type": "java.lang.String",
"sourceType": "com.qiaoba.common.database.properties.DefaultDataSourceProperties"
},
{
"name": "qiaoba.datasource.slaves.username",
"type": "java.lang.String",
"sourceType": "com.qiaoba.common.database.properties.DefaultDataSourceProperties"
},
{
"name": "qiaoba.datasource.slaves.password",
"type": "java.lang.String",
"sourceType": "com.qiaoba.common.database.properties.DefaultDataSourceProperties"
},
{
"name": "qiaoba.datasource.slaves.weight",
"type": "java.lang.String",
"sourceType": "com.qiaoba.common.database.properties.DefaultDataSourceProperties"
},
{
"name": "qiaoba.datasource.slaves.is-use",
"type": "java.lang.Boolean",
"sourceType": "com.qiaoba.common.database.properties.DefaultDataSourceProperties",
"defaultValue": true
},
{
"name": "qiaoba.datasource.slaves.pool",
"type": "com.qiaoba.common.database.properties.PoolInfo",
"sourceType": "com.qiaoba.common.database.properties.DefaultDataSourceProperties"
},
{
"name": "qiaoba.datasource.slaves.pool.init",
"type": "java.lang.Integer",
"sourceType": "com.qiaoba.common.database.properties.DefaultDataSourceProperties"
},
{
"name": "qiaoba.datasource.slaves.pool.min",
"type": "java.lang.Integer",
"sourceType": "com.qiaoba.common.database.properties.DefaultDataSourceProperties"
},
{
"name": "qiaoba.datasource.slaves.pool.max",
"type": "java.lang.Integer",
"sourceType": "com.qiaoba.common.database.properties.DefaultDataSourceProperties"
} }
], ],
"hints": [] "hints": []

View File

@ -59,11 +59,7 @@ public class SysTenantDatasource extends BaseEntity {
private Integer maxCount; private Integer maxCount;
private Integer weight; private String isPrimary;
private String isMaster = "1";
private String isUse;
@NotBlank(message = "租户ID", groups = {AddGroup.class, EditGroup.class}) @NotBlank(message = "租户ID", groups = {AddGroup.class, EditGroup.class})
@Schema(description = "租户ID") @Schema(description = "租户ID")

View File

@ -1,5 +1,6 @@
package com.qiaoba.module.tenant.entity.param; package com.qiaoba.module.tenant.entity.param;
import lombok.AllArgsConstructor;
import lombok.Getter; import lombok.Getter;
import lombok.NoArgsConstructor; import lombok.NoArgsConstructor;
import lombok.Setter; import lombok.Setter;
@ -16,21 +17,15 @@ import java.io.Serializable;
@Getter @Getter
@Setter @Setter
@NoArgsConstructor @NoArgsConstructor
@AllArgsConstructor
public class SysTenantDatasourceParam implements Serializable { public class SysTenantDatasourceParam implements Serializable {
private String tenantId; private String tenantId;
private String isMaster; private String isPrimary;
private String isUse;
public SysTenantDatasourceParam(String tenantId) { public SysTenantDatasourceParam(String tenantId) {
this.tenantId = tenantId; this.tenantId = tenantId;
} }
public SysTenantDatasourceParam(String tenantId, String isMaster) {
this.tenantId = tenantId;
this.isMaster = isMaster;
}
} }

View File

@ -3,6 +3,8 @@ package com.qiaoba.module.tenant.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.qiaoba.module.tenant.entity.SysTenantDatasource; import com.qiaoba.module.tenant.entity.SysTenantDatasource;
import java.util.List;
/** /**
* 租户数据源 数据层 * 租户数据源 数据层
* *
@ -11,4 +13,12 @@ import com.qiaoba.module.tenant.entity.SysTenantDatasource;
* @since 2023/6/7 14:47 * @since 2023/6/7 14:47
*/ */
public interface SysTenantDatasourceMapper extends BaseMapper<SysTenantDatasource> { public interface SysTenantDatasourceMapper extends BaseMapper<SysTenantDatasource> {
/**
* 查询所有数据源模式的租户ID
*
* @return tenantIds
*/
List<String> selectTenantIds();
} }

View File

@ -15,12 +15,12 @@ import java.util.List;
public interface SysTenantDatasourceService { public interface SysTenantDatasourceService {
/** /**
* 查询租户的主 * 查询租户的主要数据源
* *
* @param tenantId 租户ID * @param tenantId 租户ID
* @return 数据源 * @return 数据源
*/ */
SysTenantDatasource selectMaster(String tenantId); SysTenantDatasource selectPrimary(String tenantId);
/** /**
* 新增 * 新增
@ -61,4 +61,11 @@ public interface SysTenantDatasourceService {
* @return list * @return list
*/ */
List<SysTenantDatasource> selectList(SysTenantDatasourceParam param); List<SysTenantDatasource> selectList(SysTenantDatasourceParam param);
/**
* 查询所有数据源模式的租户ID
*
* @return tenantIds
*/
List<String> selectTenantIds();
} }

View File

@ -12,7 +12,9 @@ import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List; import java.util.List;
import java.util.Map;
/** /**
* 动态数据源接口 * 动态数据源接口
@ -28,11 +30,14 @@ public class DynamicDatasourceServiceImpl implements DynamicDatasourceService {
private final SysTenantDatasourceService sysTenantDatasourceService; private final SysTenantDatasourceService sysTenantDatasourceService;
@Override @Override
public List<DynamicDataSource> loadAllTenantDatasource() { public Map<String, List<DynamicDataSource>> loadAllTenantDatasource() {
SysTenantDatasourceParam param = new SysTenantDatasourceParam(); Map<String, List<DynamicDataSource>> datasourceMap = new LinkedHashMap<>();
param.setIsUse(BaseEnum.YES.getCode()); List<String> tenantIds = sysTenantDatasourceService.selectTenantIds();
List<SysTenantDatasource> datasourceList = sysTenantDatasourceService.selectList(param); for (String tenantId : tenantIds) {
return transform(datasourceList); List<SysTenantDatasource> datasourceList = sysTenantDatasourceService.selectList(new SysTenantDatasourceParam(tenantId));
datasourceMap.put(tenantId, transform(datasourceList));
}
return datasourceMap;
} }
private List<DynamicDataSource> transform(List<SysTenantDatasource> datasourceList) { private List<DynamicDataSource> transform(List<SysTenantDatasource> datasourceList) {

View File

@ -26,7 +26,7 @@ public class SysTenantDatasourceServiceImpl implements SysTenantDatasourceServic
private final SysTenantDatasourceMapper sysTenantDatasourceMapper; private final SysTenantDatasourceMapper sysTenantDatasourceMapper;
@Override @Override
public SysTenantDatasource selectMaster(String tenantId) { public SysTenantDatasource selectPrimary(String tenantId) {
return sysTenantDatasourceMapper.selectOne(paramToWrapper(new SysTenantDatasourceParam(tenantId, BaseEnum.YES.getCode()))); return sysTenantDatasourceMapper.selectOne(paramToWrapper(new SysTenantDatasourceParam(tenantId, BaseEnum.YES.getCode())));
} }
@ -55,13 +55,16 @@ public class SysTenantDatasourceServiceImpl implements SysTenantDatasourceServic
return sysTenantDatasourceMapper.selectList(paramToWrapper(param)); return sysTenantDatasourceMapper.selectList(paramToWrapper(param));
} }
@Override
public List<String> selectTenantIds() {
return sysTenantDatasourceMapper.selectTenantIds();
}
private QueryWrapper<SysTenantDatasource> paramToWrapper(SysTenantDatasourceParam param) { private QueryWrapper<SysTenantDatasource> paramToWrapper(SysTenantDatasourceParam param) {
QueryWrapper<SysTenantDatasource> wrapper = new QueryWrapper<>(); QueryWrapper<SysTenantDatasource> wrapper = new QueryWrapper<>();
wrapper.lambda() wrapper.lambda()
.eq(StrUtil.isNotBlank(param.getTenantId()), SysTenantDatasource::getTenantId, param.getTenantId()) .eq(StrUtil.isNotBlank(param.getTenantId()), SysTenantDatasource::getTenantId, param.getTenantId())
.eq(StrUtil.isNotBlank(param.getIsUse()), SysTenantDatasource::getIsUse, param.getIsUse()) .eq(StrUtil.isNotBlank(param.getIsPrimary()), SysTenantDatasource::getIsPrimary, param.getIsPrimary());
.eq(StrUtil.isNotBlank(param.getIsMaster()), SysTenantDatasource::getIsMaster, param.getIsMaster());
return wrapper; return wrapper;
} }
} }

View File

@ -12,13 +12,11 @@ import com.qiaoba.common.base.exceptions.ServiceException;
import com.qiaoba.common.database.config.DynamicDataSourceConfig; import com.qiaoba.common.database.config.DynamicDataSourceConfig;
import com.qiaoba.common.database.entity.PageQuery; import com.qiaoba.common.database.entity.PageQuery;
import com.qiaoba.common.database.entity.TableDataInfo; import com.qiaoba.common.database.entity.TableDataInfo;
import com.qiaoba.common.database.properties.PoolInfo;
import com.qiaoba.common.database.utils.JdbcUtil; import com.qiaoba.common.database.utils.JdbcUtil;
import com.qiaoba.common.redis.service.RedisService; import com.qiaoba.common.redis.service.RedisService;
import com.qiaoba.module.tenant.entity.SysTenant; import com.qiaoba.module.tenant.entity.SysTenant;
import com.qiaoba.module.tenant.entity.SysTenantDatasource; import com.qiaoba.module.tenant.entity.SysTenantDatasource;
import com.qiaoba.module.tenant.entity.param.SysTenantParam; import com.qiaoba.module.tenant.entity.param.SysTenantParam;
import com.qiaoba.module.tenant.entity.vo.TenantSettingVo;
import com.qiaoba.module.tenant.handler.DataHandlerFactory; import com.qiaoba.module.tenant.handler.DataHandlerFactory;
import com.qiaoba.module.tenant.mapper.SysTenantMapper; import com.qiaoba.module.tenant.mapper.SysTenantMapper;
import com.qiaoba.module.tenant.service.SysTenantDatasourceService; import com.qiaoba.module.tenant.service.SysTenantDatasourceService;
@ -121,16 +119,6 @@ public class SysTenantServiceImpl implements SysTenantService {
if (!result) { if (!result) {
throw new ServiceException("同步数据出错, 数据已回滚"); throw new ServiceException("同步数据出错, 数据已回滚");
} }
// 将数据源添加到数据源池中
if (sysTenant.getMode().equals(SysTenant.DATASOURCE_MODE)) {
SysTenantDatasource master = sysTenantDatasourceService.selectMaster(tenantId);
dynamicDataSourceConfig.addTenantDataSource(tenantId,
DataBaseEnum.getDriver(master.getType()),
DataBaseEnum.getUrl(master.getType(), master.getIp(), master.getPort(), master.getName()),
master.getUsername(),
master.getPassword(),
new PoolInfo(master.getInitCount(), master.getMinCount(), master.getMaxCount()));
}
} }
@Override @Override
@ -204,7 +192,7 @@ public class SysTenantServiceImpl implements SysTenantService {
* 处理数据源模式 * 处理数据源模式
*/ */
private Connection datasource(String tenantId) { private Connection datasource(String tenantId) {
SysTenantDatasource master = sysTenantDatasourceService.selectMaster(tenantId); SysTenantDatasource master = sysTenantDatasourceService.selectPrimary(tenantId);
if (Objects.isNull(master)) { if (Objects.isNull(master)) {
throw new ServiceException("未找到租户主数据源信息"); throw new ServiceException("未找到租户主数据源信息");
} }

View File

@ -0,0 +1,9 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.qiaoba.module.tenant.mapper.SysTenantDatasourceMapper">
<select id="selectTenantIds" resultType="string">
SELECT `tenant_id` FROM `sys_tenant_datasource` GROUP BY `tenant_id`
</select>
</mapper>