From a8f323b8612f71fd015cf9ffebd5d77caff49f8b Mon Sep 17 00:00:00 2001 From: ailanyin Date: Wed, 28 Jun 2023 22:06:29 +0800 Subject: [PATCH] first commit --- .../common/base/code/DatasourceErrorCode.java | 7 +- .../module/tenant/handler/DataHandler.java | 23 --- .../tenant/handler/DataHandlerFactory.java | 46 ----- .../tenant/handler/MysqlDataHandler.java | 175 ------------------ .../tenant/handler/OracleDataHandler.java | 25 --- .../tenant/handler/PostgreSqlHandler.java | 25 --- .../tenant/handler/SqlServerHandler.java | 25 --- .../module/tenant/init/InitDataStrategy.java | 13 ++ .../tenant/init/InitDataStrategyFactory.java | 42 +++++ .../tenant/init/InitTablesStrategy.java | 8 + .../init/impl/MysqlInitDataStrategy.java | 56 ++++++ .../init/impl/MysqlInitTablesStrategy.java | 12 ++ .../service/SysTenantDatasourceService.java | 9 + .../impl/SysTenantDatasourceServiceImpl.java | 12 ++ .../impl/SysTenantInitServiceImpl.java | 6 +- .../module/tenant/utils/InitDataUtil.java | 116 ++++++++++++ 16 files changed, 279 insertions(+), 321 deletions(-) delete mode 100644 qiaoba-modules/qiaoba-module-tenant/src/main/java/com/qiaoba/module/tenant/handler/DataHandler.java delete mode 100644 qiaoba-modules/qiaoba-module-tenant/src/main/java/com/qiaoba/module/tenant/handler/DataHandlerFactory.java delete mode 100644 qiaoba-modules/qiaoba-module-tenant/src/main/java/com/qiaoba/module/tenant/handler/MysqlDataHandler.java delete mode 100644 qiaoba-modules/qiaoba-module-tenant/src/main/java/com/qiaoba/module/tenant/handler/OracleDataHandler.java delete mode 100644 qiaoba-modules/qiaoba-module-tenant/src/main/java/com/qiaoba/module/tenant/handler/PostgreSqlHandler.java delete mode 100644 qiaoba-modules/qiaoba-module-tenant/src/main/java/com/qiaoba/module/tenant/handler/SqlServerHandler.java create mode 100644 qiaoba-modules/qiaoba-module-tenant/src/main/java/com/qiaoba/module/tenant/init/InitDataStrategyFactory.java create mode 100644 qiaoba-modules/qiaoba-module-tenant/src/main/java/com/qiaoba/module/tenant/init/impl/MysqlInitDataStrategy.java create mode 100644 qiaoba-modules/qiaoba-module-tenant/src/main/java/com/qiaoba/module/tenant/utils/InitDataUtil.java diff --git a/qiaoba-commons/qiaoba-common-base/src/main/java/com/qiaoba/common/base/code/DatasourceErrorCode.java b/qiaoba-commons/qiaoba-common-base/src/main/java/com/qiaoba/common/base/code/DatasourceErrorCode.java index 2fb3149..5788b29 100644 --- a/qiaoba-commons/qiaoba-common-base/src/main/java/com/qiaoba/common/base/code/DatasourceErrorCode.java +++ b/qiaoba-commons/qiaoba-common-base/src/main/java/com/qiaoba/common/base/code/DatasourceErrorCode.java @@ -35,7 +35,12 @@ public enum DatasourceErrorCode { /** * 创建模式/库错误 */ - CREATE_SCHEMA_ERROR(50105, "创建模式/库错误"); + CREATE_SCHEMA_ERROR(50105, "创建模式/库错误"), + + /** + * 初始化数据错误 + */ + INIT_DATA_ERROR(50106, "初始化数据错误"); private final Integer code; private final String msg; diff --git a/qiaoba-modules/qiaoba-module-tenant/src/main/java/com/qiaoba/module/tenant/handler/DataHandler.java b/qiaoba-modules/qiaoba-module-tenant/src/main/java/com/qiaoba/module/tenant/handler/DataHandler.java deleted file mode 100644 index 22eb515..0000000 --- a/qiaoba-modules/qiaoba-module-tenant/src/main/java/com/qiaoba/module/tenant/handler/DataHandler.java +++ /dev/null @@ -1,23 +0,0 @@ -package com.qiaoba.module.tenant.handler; - -import java.sql.Connection; - -/** - * 数据处理器 - * - * @author ailanyin - * @version 1.0 - * @since 2023/6/8 15:27 - */ -public interface DataHandler { - - /** - * 处理 - * - * @param conn conn - * @param needCreateTables 是否需要建表 - * @param tenantId tenantId - * @return 结果 - */ - boolean handle(Connection conn, String tenantId, Boolean needCreateTables); -} diff --git a/qiaoba-modules/qiaoba-module-tenant/src/main/java/com/qiaoba/module/tenant/handler/DataHandlerFactory.java b/qiaoba-modules/qiaoba-module-tenant/src/main/java/com/qiaoba/module/tenant/handler/DataHandlerFactory.java deleted file mode 100644 index 61b3cd3..0000000 --- a/qiaoba-modules/qiaoba-module-tenant/src/main/java/com/qiaoba/module/tenant/handler/DataHandlerFactory.java +++ /dev/null @@ -1,46 +0,0 @@ -package com.qiaoba.module.tenant.handler; - -import com.qiaoba.common.base.enums.DataBaseEnum; -import com.qiaoba.common.base.exceptions.ServiceException; -import lombok.RequiredArgsConstructor; -import org.springframework.stereotype.Component; - -import javax.annotation.PostConstruct; -import java.util.Map; -import java.util.Objects; -import java.util.concurrent.ConcurrentHashMap; - -/** - * 处理器工厂-根据不同类型的数据库-选择不同的处理器 - * - * @author ailanyin - * @version 1.0 - * @since 2023/6/8 15:34 - */ -@Component -@RequiredArgsConstructor -public class DataHandlerFactory { - - private static Map handlerMap = new ConcurrentHashMap<>(); - - private final MysqlDataHandler mysqlDataHandler; - private final OracleDataHandler oracleDataHandler; - private final PostgreSqlHandler postgreSqlHandler; - private final SqlServerHandler sqlServerHandler; - - @PostConstruct - public void register() { - handlerMap.put(DataBaseEnum.MY_SQL.getType(), mysqlDataHandler); - handlerMap.put(DataBaseEnum.ORACLE.getType(), oracleDataHandler); - handlerMap.put(DataBaseEnum.POSTGRE_SQL.getType(), postgreSqlHandler); - handlerMap.put(DataBaseEnum.SQL_SERVER.getType(), sqlServerHandler); - } - - public static DataHandler getHandler(String name) { - DataHandler dataHandler = handlerMap.get(name); - if (Objects.isNull(dataHandler)) { - throw new ServiceException("数据库处理器工厂异常, 类型:[" + name + "]找不到相对应的解析器"); - } - return dataHandler; - } -} diff --git a/qiaoba-modules/qiaoba-module-tenant/src/main/java/com/qiaoba/module/tenant/handler/MysqlDataHandler.java b/qiaoba-modules/qiaoba-module-tenant/src/main/java/com/qiaoba/module/tenant/handler/MysqlDataHandler.java deleted file mode 100644 index 2e73b43..0000000 --- a/qiaoba-modules/qiaoba-module-tenant/src/main/java/com/qiaoba/module/tenant/handler/MysqlDataHandler.java +++ /dev/null @@ -1,175 +0,0 @@ -package com.qiaoba.module.tenant.handler; - -import cn.hutool.core.io.FileUtil; -import cn.hutool.core.lang.Snowflake; -import cn.hutool.core.util.StrUtil; -import cn.hutool.db.DbUtil; -import cn.hutool.db.sql.SqlExecutor; -import com.qiaoba.module.tenant.utils.MenuUtil; -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import org.apache.ibatis.jdbc.ScriptRunner; -import org.springframework.core.io.ClassPathResource; -import org.springframework.stereotype.Component; - -import java.io.File; -import java.io.FileReader; -import java.nio.charset.Charset; -import java.sql.Connection; -import java.sql.SQLException; -import java.util.List; - -/** - * MysqlHandler - * - * @author ailanyin - * @version 1.0 - * @since 2023/6/5 16:28 - */ -@Component -@Slf4j -@RequiredArgsConstructor -public class MysqlDataHandler implements DataHandler { - - /** - * 角色-超管ID - */ - private static final ThreadLocal ROLE_SUPER_ADMIN_ID = new ThreadLocal<>(); - - /** - * 用户-超管ID - */ - private static final ThreadLocal USER_SUPER_ADMIN_ID = new ThreadLocal<>(); - - @Override - public boolean handle(Connection conn, String tenantId, Boolean needCreateTables) { - - try { - // 手动提交 - conn.setAutoCommit(false); - // 创建表 - if (needCreateTables) { - initTables(conn); - } - // 处理 sys_config - handleSysConfig(conn, tenantId); - // 处理 sys_post - handleSysPost(conn, tenantId); - // 处理 sys_role - handleSysRole(conn, tenantId); - // 处理 sys_user - handleSysUser(conn, tenantId); - // 处理 sys_user_role - bindUserAndRole(conn, tenantId); - // 处理 sys_menu - MenuUtil.handleMenu(conn, tenantId); - // 处理 sys_role_menu - bindRoleAndMenu(conn, tenantId); - conn.commit(); - return true; - } catch (Exception e) { - try { - conn.rollback(); - } catch (SQLException ex) { - ex.printStackTrace(); - } - e.printStackTrace(); - } finally { - DbUtil.close(conn); - ROLE_SUPER_ADMIN_ID.remove(); - USER_SUPER_ADMIN_ID.remove(); - } - return false; - } - - private void initTables(Connection conn) throws Exception { - ClassPathResource resource = new ClassPathResource("MySQL/table/base_tables"); - File file = resource.getFile(); - FileReader reader = new FileReader(file); - ScriptRunner scriptRunner = new ScriptRunner(conn); - scriptRunner.setSendFullScript(true); - scriptRunner.runScript(reader); - reader.close(); - } - - private void handleSysConfig(Connection conn, String tenantId) throws Exception { - handleSql(conn, tenantId, "MySQL/data/sys_config_data"); - } - - private void handleSql(Connection conn, String tenantId, String fileName) throws Exception { - ClassPathResource resource = new ClassPathResource(fileName); - List lines = FileUtil.readLines(resource.getFile(), Charset.defaultCharset()); - StringBuilder sb = new StringBuilder(); - for (String line : lines) { - if (StrUtil.isNotBlank(line)) { - Snowflake snowflake = new Snowflake(); - line = StrUtil.format(line, snowflake.nextId(), tenantId); - sb.append(line); - } - } - if (StrUtil.isNotBlank(sb.toString())) { - SqlExecutor.execute(conn, sb.toString()); - } - } - - private void handleSysPost(Connection conn, String tenantId) throws Exception { - handleSql(conn, tenantId, "MySQL/data/sys_post_data"); - } - - private void handleSysRole(Connection conn, String tenantId) throws Exception { - handleUserOrRole(conn, tenantId, "MySQL/data/sys_role_data", true); - } - - private void handleUserOrRole(Connection conn, String tenantId, String fileName, Boolean isRole) throws Exception { - ClassPathResource resource = new ClassPathResource(fileName); - List lines = FileUtil.readLines(resource.getFile(), Charset.defaultCharset()); - StringBuilder sb = new StringBuilder(); - long superAdminId = new Snowflake().nextId(); - if (isRole) { - ROLE_SUPER_ADMIN_ID.set(superAdminId); - } else { - USER_SUPER_ADMIN_ID.set(superAdminId); - } - for (int i = 0; i < lines.size(); i++) { - String line = lines.get(i); - if (StrUtil.isBlank(line)) { - continue; - } - if (i == 0) { - // 第1行是超管 - line = StrUtil.format(line, superAdminId, tenantId); - } else { - Snowflake snowflake = new Snowflake(); - line = StrUtil.format(line, snowflake.nextId(), tenantId); - } - sb.append(line); - } - if (StrUtil.isNotBlank(sb.toString())) { - SqlExecutor.execute(conn, sb.toString()); - } - } - - private void handleSysUser(Connection conn, String tenantId) throws Exception { - handleUserOrRole(conn, tenantId, "MySQL/data/sys_user_data", false); - } - - private void bindUserAndRole(Connection conn, String tenantId) throws Exception { - // user_id role_id tenant_id - String sql = StrUtil.format("INSERT INTO `sys_user_role` VALUES ({}, {}, {});", - USER_SUPER_ADMIN_ID.get(), - ROLE_SUPER_ADMIN_ID.get(), tenantId); - SqlExecutor.execute(conn, sql); - } - - private void bindRoleAndMenu(Connection conn, String tenantId) throws Exception { - String sql = "INSERT INTO `sys_role_menu` VALUES ({}, {}, {});"; - StringBuilder sb = new StringBuilder(); - List menuIds = MenuUtil.getAllMenuIdsByTenantId(conn, tenantId); - for (String menuId : menuIds) { - sb.append(StrUtil.format(sql, ROLE_SUPER_ADMIN_ID.get(), menuId, tenantId)); - } - if (StrUtil.isNotBlank(sb.toString())) { - SqlExecutor.execute(conn, sb.toString()); - } - } -} diff --git a/qiaoba-modules/qiaoba-module-tenant/src/main/java/com/qiaoba/module/tenant/handler/OracleDataHandler.java b/qiaoba-modules/qiaoba-module-tenant/src/main/java/com/qiaoba/module/tenant/handler/OracleDataHandler.java deleted file mode 100644 index 97e1d8c..0000000 --- a/qiaoba-modules/qiaoba-module-tenant/src/main/java/com/qiaoba/module/tenant/handler/OracleDataHandler.java +++ /dev/null @@ -1,25 +0,0 @@ -package com.qiaoba.module.tenant.handler; - -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import org.springframework.stereotype.Component; - -import java.sql.Connection; - -/** - * OracleDataHandler - * - * @author ailanyin - * @version 1.0 - * @since 2023/6/5 16:28 - */ -@Component -@Slf4j -@RequiredArgsConstructor -public class OracleDataHandler implements DataHandler { - - @Override - public boolean handle(Connection conn, String tenantId, Boolean needCreateTables) { - return false; - } -} diff --git a/qiaoba-modules/qiaoba-module-tenant/src/main/java/com/qiaoba/module/tenant/handler/PostgreSqlHandler.java b/qiaoba-modules/qiaoba-module-tenant/src/main/java/com/qiaoba/module/tenant/handler/PostgreSqlHandler.java deleted file mode 100644 index 065d8cf..0000000 --- a/qiaoba-modules/qiaoba-module-tenant/src/main/java/com/qiaoba/module/tenant/handler/PostgreSqlHandler.java +++ /dev/null @@ -1,25 +0,0 @@ -package com.qiaoba.module.tenant.handler; - -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import org.springframework.stereotype.Component; - -import java.sql.Connection; - -/** - * PostgreSqlHandler - * - * @author ailanyin - * @version 1.0 - * @since 2023/6/5 16:28 - */ -@Component -@Slf4j -@RequiredArgsConstructor -public class PostgreSqlHandler implements DataHandler { - - @Override - public boolean handle(Connection conn, String tenantId, Boolean needCreateTables) { - return false; - } -} diff --git a/qiaoba-modules/qiaoba-module-tenant/src/main/java/com/qiaoba/module/tenant/handler/SqlServerHandler.java b/qiaoba-modules/qiaoba-module-tenant/src/main/java/com/qiaoba/module/tenant/handler/SqlServerHandler.java deleted file mode 100644 index 0d1887e..0000000 --- a/qiaoba-modules/qiaoba-module-tenant/src/main/java/com/qiaoba/module/tenant/handler/SqlServerHandler.java +++ /dev/null @@ -1,25 +0,0 @@ -package com.qiaoba.module.tenant.handler; - -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import org.springframework.stereotype.Component; - -import java.sql.Connection; - -/** - * SqlServerHandler - * - * @author ailanyin - * @version 1.0 - * @since 2023/6/5 16:28 - */ -@Component -@Slf4j -@RequiredArgsConstructor -public class SqlServerHandler implements DataHandler { - - @Override - public boolean handle(Connection conn, String tenantId, Boolean needCreateTables) { - return false; - } -} diff --git a/qiaoba-modules/qiaoba-module-tenant/src/main/java/com/qiaoba/module/tenant/init/InitDataStrategy.java b/qiaoba-modules/qiaoba-module-tenant/src/main/java/com/qiaoba/module/tenant/init/InitDataStrategy.java index bbc1159..d500e89 100644 --- a/qiaoba-modules/qiaoba-module-tenant/src/main/java/com/qiaoba/module/tenant/init/InitDataStrategy.java +++ b/qiaoba-modules/qiaoba-module-tenant/src/main/java/com/qiaoba/module/tenant/init/InitDataStrategy.java @@ -1,5 +1,9 @@ package com.qiaoba.module.tenant.init; +import com.qiaoba.module.tenant.entity.vo.TenantInitVo; + +import java.sql.Connection; + /** * 初始化数据策略 * @@ -8,4 +12,13 @@ package com.qiaoba.module.tenant.init; * @since 2023/6/27 13:05 */ public interface InitDataStrategy { + + /** + * 初始化数据 + * + * @param conn 连接对象 + * @param tenantId 租户ID + * @return 结果 + */ + TenantInitVo init(Connection conn, String tenantId); } diff --git a/qiaoba-modules/qiaoba-module-tenant/src/main/java/com/qiaoba/module/tenant/init/InitDataStrategyFactory.java b/qiaoba-modules/qiaoba-module-tenant/src/main/java/com/qiaoba/module/tenant/init/InitDataStrategyFactory.java new file mode 100644 index 0000000..b0677b3 --- /dev/null +++ b/qiaoba-modules/qiaoba-module-tenant/src/main/java/com/qiaoba/module/tenant/init/InitDataStrategyFactory.java @@ -0,0 +1,42 @@ +package com.qiaoba.module.tenant.init; + +import com.qiaoba.common.base.enums.DataBaseEnum; +import com.qiaoba.common.base.exceptions.ServiceException; +import com.qiaoba.module.tenant.init.impl.MysqlInitDataStrategy; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Component; + +import javax.annotation.PostConstruct; +import java.util.Map; +import java.util.Objects; +import java.util.concurrent.ConcurrentHashMap; + +/** + * 策略工厂-租户初始化-导入数据 + * + * @author ailanyin + * @version 1.0 + * @since 2023/6/27 16:41 + */ +@Component +@RequiredArgsConstructor +public class InitDataStrategyFactory { + + private static Map FACTORY = new ConcurrentHashMap<>(); + + private final MysqlInitDataStrategy mysqlInitDataStrategy; + + + @PostConstruct + public void register() { + FACTORY.put(DataBaseEnum.MY_SQL.getType(), mysqlInitDataStrategy); + } + + public static InitDataStrategy getStrategy(String name) { + InitDataStrategy strategy = FACTORY.get(name); + if (Objects.isNull(strategy)) { + throw new ServiceException("[ InitDataStrategy ]策略工厂异常, 类型:[" + name + "]找不到相对应的策略"); + } + return strategy; + } +} diff --git a/qiaoba-modules/qiaoba-module-tenant/src/main/java/com/qiaoba/module/tenant/init/InitTablesStrategy.java b/qiaoba-modules/qiaoba-module-tenant/src/main/java/com/qiaoba/module/tenant/init/InitTablesStrategy.java index 8591ed1..5d4069b 100644 --- a/qiaoba-modules/qiaoba-module-tenant/src/main/java/com/qiaoba/module/tenant/init/InitTablesStrategy.java +++ b/qiaoba-modules/qiaoba-module-tenant/src/main/java/com/qiaoba/module/tenant/init/InitTablesStrategy.java @@ -21,4 +21,12 @@ public interface InitTablesStrategy { * @return 结果 */ TenantInitVo create(Connection conn, String schema); + + /** + * 创建表 + * + * @param conn 连接对象 + * @return 结果 + */ + TenantInitVo create(Connection conn); } diff --git a/qiaoba-modules/qiaoba-module-tenant/src/main/java/com/qiaoba/module/tenant/init/impl/MysqlInitDataStrategy.java b/qiaoba-modules/qiaoba-module-tenant/src/main/java/com/qiaoba/module/tenant/init/impl/MysqlInitDataStrategy.java new file mode 100644 index 0000000..9a45a0a --- /dev/null +++ b/qiaoba-modules/qiaoba-module-tenant/src/main/java/com/qiaoba/module/tenant/init/impl/MysqlInitDataStrategy.java @@ -0,0 +1,56 @@ +package com.qiaoba.module.tenant.init.impl; + +import cn.hutool.db.DbUtil; +import cn.hutool.http.HttpStatus; +import com.qiaoba.common.base.code.DatasourceErrorCode; +import com.qiaoba.module.tenant.entity.vo.TenantInitVo; +import com.qiaoba.module.tenant.init.InitDataStrategy; +import com.qiaoba.module.tenant.utils.InitDataUtil; +import org.springframework.stereotype.Component; + +import java.sql.Connection; +import java.sql.SQLException; + +/** + * 初始化数据策略 + * + * @author ailanyin + * @version 1.0 + * @since 2023/6/27 13:05 + */ +@Component +public class MysqlInitDataStrategy implements InitDataStrategy { + @Override + public TenantInitVo init(Connection conn, String tenantId) { + + try { + // 手动提交 + conn.setAutoCommit(false); + // 处理 sys_config + InitDataUtil.handleSysConfig(conn, tenantId, "MySQL/data/sys_config_data"); + // 处理 sys_post + InitDataUtil.handleSysPost(conn, tenantId, "MySQL/data/sys_post_data"); + // 处理 sys_role + InitDataUtil.handleSysRole(conn, tenantId, "MySQL/data/sys_role_data"); + // 处理 sys_user + InitDataUtil.handleSysUser(conn, tenantId, "MySQL/data/sys_user_data"); + // 处理 sys_user_role + InitDataUtil.bindUserAndRole(conn, tenantId); + // 处理 sys_menu todo + //MenuUtil.handleMenu(conn, tenantId); + // 处理 sys_role_menu + InitDataUtil.bindRoleAndMenu(conn, tenantId); + conn.commit(); + return new TenantInitVo(HttpStatus.HTTP_OK, null); + } catch (Exception e) { + try { + conn.rollback(); + } catch (SQLException ex) { + ex.printStackTrace(); + } + return new TenantInitVo(DatasourceErrorCode.INIT_DATA_ERROR.getCode(), e.getMessage()); + } finally { + DbUtil.close(conn); + } + } +} diff --git a/qiaoba-modules/qiaoba-module-tenant/src/main/java/com/qiaoba/module/tenant/init/impl/MysqlInitTablesStrategy.java b/qiaoba-modules/qiaoba-module-tenant/src/main/java/com/qiaoba/module/tenant/init/impl/MysqlInitTablesStrategy.java index 566224f..158e88f 100644 --- a/qiaoba-modules/qiaoba-module-tenant/src/main/java/com/qiaoba/module/tenant/init/impl/MysqlInitTablesStrategy.java +++ b/qiaoba-modules/qiaoba-module-tenant/src/main/java/com/qiaoba/module/tenant/init/impl/MysqlInitTablesStrategy.java @@ -52,4 +52,16 @@ public class MysqlInitTablesStrategy implements InitTablesStrategy { } } + + @Override + public TenantInitVo create(Connection conn) { + try { + DbUtil.runScript(conn, "MySQL/table/base_tables"); + return new TenantInitVo(HttpStatus.HTTP_OK, null); + } catch (IOException e) { + return new TenantInitVo(DatasourceErrorCode.CREATE_TABLE_ERROR.getCode(), e.getMessage()); + } finally { + IoUtil.close(conn); + } + } } diff --git a/qiaoba-modules/qiaoba-module-tenant/src/main/java/com/qiaoba/module/tenant/service/SysTenantDatasourceService.java b/qiaoba-modules/qiaoba-module-tenant/src/main/java/com/qiaoba/module/tenant/service/SysTenantDatasourceService.java index 4b8943c..15e8533 100644 --- a/qiaoba-modules/qiaoba-module-tenant/src/main/java/com/qiaoba/module/tenant/service/SysTenantDatasourceService.java +++ b/qiaoba-modules/qiaoba-module-tenant/src/main/java/com/qiaoba/module/tenant/service/SysTenantDatasourceService.java @@ -22,6 +22,15 @@ public interface SysTenantDatasourceService { */ SysTenantDatasource selectPrimary(String tenantId); + /** + * 查询租户的主要数据源 + * + * @param tenantId 租户ID + * @param allowNull 允许空 + * @return 数据源 + */ + SysTenantDatasource selectPrimary(String tenantId, boolean allowNull); + /** * 通过IP查询 * diff --git a/qiaoba-modules/qiaoba-module-tenant/src/main/java/com/qiaoba/module/tenant/service/impl/SysTenantDatasourceServiceImpl.java b/qiaoba-modules/qiaoba-module-tenant/src/main/java/com/qiaoba/module/tenant/service/impl/SysTenantDatasourceServiceImpl.java index 1e02427..d832541 100644 --- a/qiaoba-modules/qiaoba-module-tenant/src/main/java/com/qiaoba/module/tenant/service/impl/SysTenantDatasourceServiceImpl.java +++ b/qiaoba-modules/qiaoba-module-tenant/src/main/java/com/qiaoba/module/tenant/service/impl/SysTenantDatasourceServiceImpl.java @@ -2,8 +2,10 @@ package com.qiaoba.module.tenant.service.impl; import cn.hutool.core.util.StrUtil; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.qiaoba.common.base.code.DatasourceErrorCode; import com.qiaoba.common.base.constants.BaseConstant; import com.qiaoba.common.base.enums.BaseEnum; +import com.qiaoba.common.base.exceptions.ServiceException; import com.qiaoba.module.tenant.entity.SysTenantDatasource; import com.qiaoba.module.tenant.entity.param.SysTenantDatasourceParam; import com.qiaoba.module.tenant.mapper.SysTenantDatasourceMapper; @@ -13,6 +15,7 @@ import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import java.util.List; +import java.util.Objects; /** * 租户数据源 服务层实现 @@ -32,6 +35,15 @@ public class SysTenantDatasourceServiceImpl implements SysTenantDatasourceServic return sysTenantDatasourceMapper.selectOne(paramToWrapper(new SysTenantDatasourceParam(tenantId, BaseEnum.YES.getCode()))); } + @Override + public SysTenantDatasource selectPrimary(String tenantId, boolean allowNull) { + SysTenantDatasource primary = selectPrimary(tenantId); + if (!allowNull && Objects.isNull(primary)) { + throw new ServiceException(DatasourceErrorCode.NOT_FIND.getCode(), DatasourceErrorCode.NOT_FIND.getMsg()); + } + return primary; + } + @Override public SysTenantDatasource selectByIp(String tenantId, String ip) { SysTenantDatasourceParam param = new SysTenantDatasourceParam(tenantId); diff --git a/qiaoba-modules/qiaoba-module-tenant/src/main/java/com/qiaoba/module/tenant/service/impl/SysTenantInitServiceImpl.java b/qiaoba-modules/qiaoba-module-tenant/src/main/java/com/qiaoba/module/tenant/service/impl/SysTenantInitServiceImpl.java index e6b7701..1c17207 100644 --- a/qiaoba-modules/qiaoba-module-tenant/src/main/java/com/qiaoba/module/tenant/service/impl/SysTenantInitServiceImpl.java +++ b/qiaoba-modules/qiaoba-module-tenant/src/main/java/com/qiaoba/module/tenant/service/impl/SysTenantInitServiceImpl.java @@ -94,7 +94,11 @@ public class SysTenantInitServiceImpl implements SysTenantInitService { } // 数据源模式 if (SysTenant.DATASOURCE_MODE.equals(sysTenant.getMode())) { - + SysTenantDatasource primary = sysTenantDatasourceService.selectPrimary(tenantId, false); + Connection connection = JdbcUtil.getConnection(DataBaseEnum.getDriver(primary.getType()), + DataBaseEnum.getUrl(primary.getType(), primary.getIp(), primary.getPort(), primary.getDbName(), primary.getSchemaName()), + primary.getUsername(), primary.getPassword()); + return InitTablesStrategyFactory.getStrategy(primary.getType()).create(connection); } return new TenantInitVo(500, "未知异常"); } diff --git a/qiaoba-modules/qiaoba-module-tenant/src/main/java/com/qiaoba/module/tenant/utils/InitDataUtil.java b/qiaoba-modules/qiaoba-module-tenant/src/main/java/com/qiaoba/module/tenant/utils/InitDataUtil.java new file mode 100644 index 0000000..78af474 --- /dev/null +++ b/qiaoba-modules/qiaoba-module-tenant/src/main/java/com/qiaoba/module/tenant/utils/InitDataUtil.java @@ -0,0 +1,116 @@ +package com.qiaoba.module.tenant.utils; + +import cn.hutool.core.io.FileUtil; +import cn.hutool.core.lang.Snowflake; +import cn.hutool.core.util.StrUtil; +import cn.hutool.db.sql.SqlExecutor; +import org.springframework.core.io.ClassPathResource; + +import java.nio.charset.Charset; +import java.sql.Connection; +import java.util.List; + +/** + * 数据初始化工具类 + * + * @author ailanyin + * @version 1.0 + * @since 2023/6/5 16:28 + */ +public class InitDataUtil { + + private InitDataUtil() { + } + + /** + * 角色-超管ID + */ + private static final ThreadLocal ROLE_SUPER_ADMIN_ID = new ThreadLocal<>(); + + /** + * 用户-超管ID + */ + private static final ThreadLocal USER_SUPER_ADMIN_ID = new ThreadLocal<>(); + + + public static void handleSysConfig(Connection conn, String tenantId, String filePath) throws Exception { + handleSql(conn, tenantId, filePath); + } + + public static void handleSysPost(Connection conn, String tenantId, String filePath) throws Exception { + handleSql(conn, tenantId, filePath); + } + + public static void handleSysRole(Connection conn, String tenantId, String filePath) throws Exception { + handleUserOrRole(conn, tenantId, filePath, true); + } + + private static void handleUserOrRole(Connection conn, String tenantId, String filePath, Boolean isRole) throws Exception { + ClassPathResource resource = new ClassPathResource(filePath); + List lines = FileUtil.readLines(resource.getFile(), Charset.defaultCharset()); + StringBuilder sb = new StringBuilder(); + long superAdminId = new Snowflake().nextId(); + if (isRole) { + ROLE_SUPER_ADMIN_ID.set(superAdminId); + } else { + USER_SUPER_ADMIN_ID.set(superAdminId); + } + for (int i = 0; i < lines.size(); i++) { + String line = lines.get(i); + if (StrUtil.isBlank(line)) { + continue; + } + if (i == 0) { + // 第1行是超管 + line = StrUtil.format(line, superAdminId, tenantId); + } else { + Snowflake snowflake = new Snowflake(); + line = StrUtil.format(line, snowflake.nextId(), tenantId); + } + sb.append(line); + } + if (StrUtil.isNotBlank(sb.toString())) { + SqlExecutor.execute(conn, sb.toString()); + } + } + + public static void handleSysUser(Connection conn, String tenantId, String filePath) throws Exception { + handleUserOrRole(conn, tenantId, filePath, false); + } + + public static void bindUserAndRole(Connection conn, String tenantId) throws Exception { + // user_id role_id tenant_id + String sql = StrUtil.format("INSERT INTO sys_user_role VALUES ('{}', '{}', '{}');", + USER_SUPER_ADMIN_ID.get(), + ROLE_SUPER_ADMIN_ID.get(), tenantId); + SqlExecutor.execute(conn, sql); + } + + public static void bindRoleAndMenu(Connection conn, String tenantId) throws Exception { + String sql = "INSERT INTO sys_role_menu VALUES ('{}', '{}', '{}');"; + StringBuilder sb = new StringBuilder(); + List menuIds = MenuUtil.getAllMenuIdsByTenantId(conn, tenantId); + for (String menuId : menuIds) { + sb.append(StrUtil.format(sql, ROLE_SUPER_ADMIN_ID.get(), menuId, tenantId)); + } + if (StrUtil.isNotBlank(sb.toString())) { + SqlExecutor.execute(conn, sb.toString()); + } + } + + private static void handleSql(Connection conn, String tenantId, String filePath) throws Exception { + ClassPathResource resource = new ClassPathResource(filePath); + List lines = FileUtil.readLines(resource.getFile(), Charset.defaultCharset()); + StringBuilder sb = new StringBuilder(); + for (String line : lines) { + if (StrUtil.isNotBlank(line)) { + Snowflake snowflake = new Snowflake(); + line = StrUtil.format(line, snowflake.nextId(), tenantId); + sb.append(line); + } + } + if (StrUtil.isNotBlank(sb.toString())) { + SqlExecutor.execute(conn, sb.toString()); + } + } +}