This commit is contained in:
2023-06-15 16:17:13 +08:00
parent a7ee9eadba
commit 076955a04f
20 changed files with 941 additions and 73 deletions

View File

@ -36,7 +36,7 @@ public enum DataBaseEnum {
* PostgreSQL
*/
POSTGRE_SQL("PostgreSQL",
"jdbc:postgresql://localhost:5432/{}?useUnicode=true&characterEncoding=utf8&useSSL=true&autoReconnect=true&reWriteBatchedInserts=true",
"jdbc:postgresql://{}:{}/mydb?currentSchema={}&useUnicode=true&characterEncoding=utf-8&serverTimezone=Asia/Shanghai&nullCatalogMeansCurrent=true&allowMultiQueries=true",
"org.postgresql.Driver"),
/**
@ -50,17 +50,6 @@ public enum DataBaseEnum {
private final String url;
private final String driver;
public static DataBaseEnum find(String databaseProductName) {
if (StrUtil.isBlank(databaseProductName)) {
return null;
}
for (DataBaseEnum type : values()) {
if (type.getType().equals(databaseProductName)) {
return type;
}
}
return null;
}
public static String getDriver(String type) {
for (DataBaseEnum dataBaseEnum : values()) {

View File

@ -23,15 +23,16 @@ public class DatabaseUtil {
* @return 处理后的sql
*/
public static String handleFindInSet(Object var1, String var2) {
DataBaseEnum dataBaseType = DataBaseEnum.find(BaseContext.getDatabaseType());
String databaseType = BaseContext.getDatabaseType();
log.debug("租户ID: [{}], 数据源类型: {}", BaseContext.getTenantId(), databaseType);
String var = Convert.toStr(var1);
if (dataBaseType == DataBaseEnum.SQL_SERVER) {
if (DataBaseEnum.SQL_SERVER.getType().equals(databaseType)) {
// charindex(',100,' , ',0,100,101,') <> 0
return "charindex('," + var + ",' , ','+" + var2 + "+',') <> 0";
} else if (dataBaseType == DataBaseEnum.POSTGRE_SQL) {
} else if (DataBaseEnum.POSTGRE_SQL.getType().equals(databaseType)) {
// (select position(',100,' in ',0,100,101,')) <> 0
return "(select position('," + var + ",' in ','||" + var2 + "||',')) <> 0";
} else if (dataBaseType == DataBaseEnum.ORACLE) {
} else if (DataBaseEnum.ORACLE.getType().equals(databaseType)) {
// instr(',0,100,101,' , ',100,') <> 0
return "instr(','||" + var2 + "||',' , '," + var + ",') <> 0";
}

View File

@ -17,11 +17,16 @@
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
</dependency>
<!-- Mysql Connector -->
<!-- Mysql -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<!-- PgSql -->
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
</dependency>
<!-- mybatis plus -->
<dependency>
<groupId>com.baomidou</groupId>
@ -33,4 +38,4 @@
</dependency>
</dependencies>
</project>
</project>

View File

@ -3,6 +3,7 @@ package com.qiaoba.common.database.config;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.ListUtil;
import com.alibaba.druid.pool.DruidDataSource;
import com.alibaba.druid.pool.DruidPooledConnection;
import com.qiaoba.common.base.constants.TenantConstant;
import com.qiaoba.common.base.context.BaseContext;
import com.qiaoba.common.base.enums.BaseEnum;
@ -64,6 +65,11 @@ public class DynamicDataSourceConfig {
*/
public static List<String> TENANT_IDS = ListUtil.toList(TenantConstant.DEFAULT_TENANT_ID);
/**
* 租户数据源类型
*/
public static Map<String, String> TENANT_DATASOURCE_TYPE_MAP = new ConcurrentHashMap<>();
/**
* 把DynamicDataSourceContext 纳入容器管理其他地方使用DynamicDataSourceConfig 类可以直接从容器取对象并调用freshDataSource方法
*/
@ -83,7 +89,7 @@ public class DynamicDataSourceConfig {
private void initDefault() {
List<DynamicDataSource> dataSources = dataSourceProperties.getDataSources();
// 0索引作为主数据源
addPrimaryMap(DynamicDatasourceConstant.MASTER_PREFIX + TenantConstant.DEFAULT_TENANT_ID, buildDataSource(dataSources.get(0)));
addPrimaryMap(DynamicDatasourceConstant.MASTER_PREFIX + TenantConstant.DEFAULT_TENANT_ID, buildDataSource(TenantConstant.DEFAULT_TENANT_ID, dataSources.get(0)));
dataSources.remove(0);
// 非0索引的备用
addBackupMap(TenantConstant.DEFAULT_TENANT_ID, dataSources);
@ -99,7 +105,7 @@ public class DynamicDataSourceConfig {
for (int i = 0; i < dataSources.size(); i++) {
DynamicDataSource dynamicDataSource = dataSources.get(i);
if (BaseEnum.YES.getCode().equals(dynamicDataSource.getIsPrimary())) {
addPrimaryMap(DynamicDatasourceConstant.MASTER_PREFIX + tenantId, buildDataSource(dataSources.get(i)));
addPrimaryMap(DynamicDatasourceConstant.MASTER_PREFIX + tenantId, buildDataSource(dataSources.get(i).getTenantId(), dataSources.get(i)));
// 去除主要数据源,剩下皆为备用数据源
dataSources.remove(i);
break;
@ -125,11 +131,11 @@ public class DynamicDataSourceConfig {
dataSource.freshDataSource(PRIMARY_DATASOURCE_MAP);
}
public static Object buildDataSource(DynamicDataSource dynamicDataSource) {
log.debug("正在创建数据源DataSource, 租户: {}", dynamicDataSource.getTenantId());
public static Object buildDataSource(String tenantId, DynamicDataSource dynamicDataSource) {
log.debug("正在创建数据源DataSource, 租户: {}", tenantId);
boolean connect = JdbcUtil.checkConnect(dynamicDataSource.getDriver(), dynamicDataSource.getUrl(), dynamicDataSource.getUsername(), dynamicDataSource.getPassword());
if (!connect) {
log.error("租户: {} 数据源连接失败, Url: {}", dynamicDataSource.getTenantId(), dynamicDataSource.getUrl());
log.error("租户: {} 数据源连接失败, Url: {}", tenantId, dynamicDataSource.getUrl());
return null;
}
DruidDataSource dataSource = new DruidDataSource();
@ -142,7 +148,13 @@ public class DynamicDataSourceConfig {
dataSource.setMaxActive(dynamicDataSource.getMaxActive());
dataSource.setKeepAlive(false);
try {
// 初始化数据源
dataSource.init();
// 将数据源的类型保存
DruidPooledConnection connection = dataSource.getConnection();
TENANT_DATASOURCE_TYPE_MAP.put(tenantId, connection.getMetaData().getDatabaseProductName());
// 归还 connection
connection.close();
return dataSource;
} catch (Exception e) {
dataSource.close();
@ -184,5 +196,6 @@ public class DynamicDataSourceConfig {
public void setDefaultSetting() {
BaseContext.setDataSource(DynamicDatasourceConstant.MASTER_PREFIX + TenantConstant.DEFAULT_TENANT_ID);
BaseContext.setTenantId(TenantConstant.DEFAULT_TENANT_ID);
BaseContext.setDatabaseType(TENANT_DATASOURCE_TYPE_MAP.get(TenantConstant.DEFAULT_TENANT_ID));
}
}

View File

@ -114,7 +114,7 @@ public class DatasourceConnectionMonitor {
Integer backupIndex = null;
for (int i = 0; i < dataSources.size(); i++) {
Object dynamicDataSource = DynamicDataSourceConfig.buildDataSource(dataSources.get(i));
Object dynamicDataSource = DynamicDataSourceConfig.buildDataSource(tenantId, dataSources.get(i));
// 不是空,说明备用数据源有用
if (Objects.nonNull(dynamicDataSource)) {
dynamicDataSourceConfig.changePrimaryDatasource(tenantId, dynamicDataSource);

View File

@ -6,7 +6,6 @@ import com.qiaoba.common.base.exceptions.ServiceException;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
/**
* JdbcUtil
@ -29,15 +28,12 @@ public class JdbcUtil {
public static boolean checkConnect(String driver, String url, String username, String password) {
Connection conn = null;
try {
try {
Class.forName(driver);
//建立连接
conn = DriverManager.getConnection(url, username, password);
return true;
} catch (SQLException e) {
return false;
}
Class.forName(driver);
//建立连接
conn = DriverManager.getConnection(url, username, password);
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
} finally {
IoUtil.close(conn);