From d79549b48a635c856f8b8c26b1d2155f56163096 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Thu, 28 Apr 2022 19:27:59 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BC=98=E5=8C=96=E4=BB=A3=E7=A0=81=E7=94=9F?= =?UTF-8?q?=E6=88=90=E5=99=A8=E5=AE=9E=E7=8E=B0=EF=BC=8C=E5=A2=9E=E5=8A=A0?= =?UTF-8?q?=20DatabaseTableDAO=20=E6=8A=BD=E8=B1=A1=EF=BC=8C=E6=94=AF?= =?UTF-8?q?=E6=8C=81=E5=A4=9A=20db=20=E7=B1=BB=E5=9E=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../mybatis/core/util/DatabaseUtils.java | 29 ------- .../mybatis/core/util/JdbcUtils.java | 85 +++++++++++++++++++ .../admin/codegen/CodegenController.java | 4 +- .../infra/convert/codegen/CodegenConvert.java | 12 +-- .../dataobject/codegen/CodegenColumnDO.java | 1 - .../dal/dataobject/db/DataSourceConfigDO.java | 5 ++ .../DatabaseColumnDO.java} | 8 +- .../DatabaseTableDO.java} | 10 +-- .../dal/mysql/codegen/SchemaColumnMapper.java | 19 ----- .../dal/mysql/codegen/SchemaTableMapper.java | 26 ------ .../infra/dal/mysql/db/DatabaseTableDAO.java | 57 +++++++++++++ .../mysql/db/DatabaseTableMySQLDAOImpl.java | 70 +++++++++++++++ .../infra/service/codegen/CodegenService.java | 4 +- .../service/codegen/CodegenServiceImpl.java | 39 ++++----- .../service/codegen/inner/CodegenBuilder.java | 12 +-- .../codegen/inner/CodegenSQLParser.java | 30 +++---- .../service/db/DataSourceConfigService.java | 3 +- .../db/DataSourceConfigServiceImpl.java | 33 +++++-- .../service/db/DatabaseTableService.java | 43 ++++++++++ .../service/db/DatabaseTableServiceImpl.java | 74 ++++++++++++++++ .../db/DataSourceConfigServiceImplTest.java | 10 +-- 21 files changed, 419 insertions(+), 155 deletions(-) delete mode 100644 yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/mybatis/core/util/DatabaseUtils.java create mode 100644 yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/mybatis/core/util/JdbcUtils.java rename yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/dataobject/{codegen/SchemaColumnDO.java => db/DatabaseColumnDO.java} (67%) rename yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/dataobject/{codegen/SchemaTableDO.java => db/DatabaseTableDO.java} (56%) delete mode 100644 yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/mysql/codegen/SchemaColumnMapper.java delete mode 100644 yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/mysql/codegen/SchemaTableMapper.java create mode 100644 yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/mysql/db/DatabaseTableDAO.java create mode 100644 yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/mysql/db/DatabaseTableMySQLDAOImpl.java create mode 100644 yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/db/DatabaseTableService.java create mode 100644 yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/db/DatabaseTableServiceImpl.java diff --git a/yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/mybatis/core/util/DatabaseUtils.java b/yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/mybatis/core/util/DatabaseUtils.java deleted file mode 100644 index b282656c5..000000000 --- a/yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/mybatis/core/util/DatabaseUtils.java +++ /dev/null @@ -1,29 +0,0 @@ -package cn.iocoder.yudao.framework.mybatis.core.util; - -import java.sql.Connection; -import java.sql.DriverManager; - -/** - * 数据库工具类 - * - * @author 芋道源码 - */ -public class DatabaseUtils { - - /** - * 判断连接是否正确 - * - * @param url 数据源连接 - * @param username 账号 - * @param password 密码 - * @return 是否正确 - */ - public static boolean isConnectionOK(String url, String username, String password) { - try (Connection ignored = DriverManager.getConnection(url, username, password)) { - return true; - } catch (Exception ex) { - return false; - } - } - -} diff --git a/yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/mybatis/core/util/JdbcUtils.java b/yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/mybatis/core/util/JdbcUtils.java new file mode 100644 index 000000000..f3e875e3c --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/mybatis/core/util/JdbcUtils.java @@ -0,0 +1,85 @@ +package cn.iocoder.yudao.framework.mybatis.core.util; + +import com.baomidou.mybatisplus.annotation.DbType; +import lombok.SneakyThrows; +import org.springframework.dao.DataAccessException; +import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.jdbc.core.RowCallbackHandler; +import org.springframework.jdbc.core.RowMapper; + +import java.sql.*; +import java.util.ArrayList; +import java.util.List; + +/** + * JDBC 工具类 + * + * @author 芋道源码 + */ +public class JdbcUtils { + + /** + * 判断连接是否正确 + * + * @param url 数据源连接 + * @param username 账号 + * @param password 密码 + * @return 是否正确 + */ + public static boolean isConnectionOK(String url, String username, String password) { + try (Connection ignored = DriverManager.getConnection(url, username, password)) { + return true; + } catch (Exception ex) { + return false; + } + } + + /** + * 获得连接 + * + * @param url 数据源连接 + * @param username 账号 + * @param password 密码 + * @return 是否正确 + */ + @SneakyThrows + public static Connection getConnection(String url, String username, String password) { + return DriverManager.getConnection(url, username, password); + } + + /** + * 执行指定 SQL,返回查询列表 + * + * 参考 {@link JdbcTemplate#query(String, RowMapper)} 实现,主要考虑 JdbcTemplate 不支持使用指定 Connection 查询 + * + * @param connection 数据库连接 + * @param sql SQL + * @param handler 行处理器 + * @return 列表 + */ + @SneakyThrows + public static List query(Connection connection, String sql, RowMapper handler) { + try (PreparedStatement ps = connection.prepareStatement(sql); + ResultSet rs = ps.executeQuery()) { + // 处理结果 + List result = new ArrayList<>(); + int rowNum = 0; + while (rs.next()) { + result.add(handler.mapRow(rs, rowNum++)); + } + return result; + } + } + + /** + * 获得 URL 对应的 DB 类型 + * + * @param url URL + * @return DB 类型 + */ + public static DbType getDbType(String url) { + String name = com.alibaba.druid.util.JdbcUtils.getDbType(url, null); + return DbType.getDbType(name); + } + +} diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/codegen/CodegenController.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/codegen/CodegenController.java index 9b6b87048..40bd69271 100644 --- a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/codegen/CodegenController.java +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/codegen/CodegenController.java @@ -13,7 +13,7 @@ import cn.iocoder.yudao.module.infra.controller.admin.codegen.vo.table.SchemaTab import cn.iocoder.yudao.module.infra.convert.codegen.CodegenConvert; import cn.iocoder.yudao.module.infra.dal.dataobject.codegen.CodegenColumnDO; import cn.iocoder.yudao.module.infra.dal.dataobject.codegen.CodegenTableDO; -import cn.iocoder.yudao.module.infra.dal.dataobject.codegen.SchemaTableDO; +import cn.iocoder.yudao.module.infra.dal.dataobject.db.DatabaseTableDO; import cn.iocoder.yudao.module.infra.service.codegen.CodegenService; import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; import cn.iocoder.yudao.framework.common.util.servlet.ServletUtils; @@ -58,7 +58,7 @@ public class CodegenController { @RequestParam(value = "tableName", required = false) String tableName, @RequestParam(value = "tableComment", required = false) String tableComment) { // 获得数据库自带的表定义列表 - List schemaTables = codegenService.getSchemaTableList(tableName, tableComment); + List schemaTables = codegenService.getSchemaTableList(tableName, tableComment); // 移除在 Codegen 中,已经存在的 Set existsTables = CollectionUtils.convertSet(codegenService.getCodeGenTableList(), CodegenTableDO::getTableName); schemaTables.removeIf(table -> existsTables.contains(table.getTableName())); diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/convert/codegen/CodegenConvert.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/convert/codegen/CodegenConvert.java index 9f5d8583f..ce14ce40c 100644 --- a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/convert/codegen/CodegenConvert.java +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/convert/codegen/CodegenConvert.java @@ -9,8 +9,8 @@ import cn.iocoder.yudao.module.infra.controller.admin.codegen.vo.table.CodegenTa import cn.iocoder.yudao.module.infra.controller.admin.codegen.vo.table.SchemaTableRespVO; import cn.iocoder.yudao.module.infra.dal.dataobject.codegen.CodegenColumnDO; import cn.iocoder.yudao.module.infra.dal.dataobject.codegen.CodegenTableDO; -import cn.iocoder.yudao.module.infra.dal.dataobject.codegen.SchemaColumnDO; -import cn.iocoder.yudao.module.infra.dal.dataobject.codegen.SchemaTableDO; +import cn.iocoder.yudao.module.infra.dal.dataobject.db.DatabaseColumnDO; +import cn.iocoder.yudao.module.infra.dal.dataobject.db.DatabaseTableDO; import org.mapstruct.Mapper; import org.mapstruct.factory.Mappers; @@ -25,11 +25,11 @@ public interface CodegenConvert { // ========== InformationSchemaTableDO 和 InformationSchemaColumnDO 相关 ========== - CodegenTableDO convert(SchemaTableDO bean); + CodegenTableDO convert(DatabaseTableDO bean); - List convertList(List list); + List convertList(List list); - CodegenTableRespVO convert(SchemaColumnDO bean); + CodegenTableRespVO convert(DatabaseColumnDO bean); // ========== CodegenTableDO 相关 ========== @@ -47,7 +47,7 @@ public interface CodegenConvert { List convertList03(List columns); - List convertList04(List list); + List convertList04(List list); // ========== 其它 ========== diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/dataobject/codegen/CodegenColumnDO.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/dataobject/codegen/CodegenColumnDO.java index 355b0f9e6..518552255 100644 --- a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/dataobject/codegen/CodegenColumnDO.java +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/dataobject/codegen/CodegenColumnDO.java @@ -74,7 +74,6 @@ public class CodegenColumnDO extends BaseDO { /** * Java 属性名 */ -// @NotBlank(message = "Java属性不能为空") private String javaField; /** * 字典类型 diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/dataobject/db/DataSourceConfigDO.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/dataobject/db/DataSourceConfigDO.java index 6508d1d18..a8450831a 100644 --- a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/dataobject/db/DataSourceConfigDO.java +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/dataobject/db/DataSourceConfigDO.java @@ -13,6 +13,11 @@ import lombok.Data; @Data public class DataSourceConfigDO extends BaseDO { + /** + * 主键编号 - Master 数据源 + */ + public static final Long ID_MASTER = 0L; + /** * 主键编号 */ diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/dataobject/codegen/SchemaColumnDO.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/dataobject/db/DatabaseColumnDO.java similarity index 67% rename from yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/dataobject/codegen/SchemaColumnDO.java rename to yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/dataobject/db/DatabaseColumnDO.java index 0d7cd6cbd..f8f62151f 100644 --- a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/dataobject/codegen/SchemaColumnDO.java +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/dataobject/db/DatabaseColumnDO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.module.infra.dal.dataobject.codegen; +package cn.iocoder.yudao.module.infra.dal.dataobject.db; import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableName; @@ -10,10 +10,9 @@ import lombok.Data; * * @author 芋道源码 */ -@TableName(value = "information_schema.columns", autoResultMap = true) @Data @Builder -public class SchemaColumnDO { +public class DatabaseColumnDO { /** * 表名称 @@ -34,17 +33,14 @@ public class SchemaColumnDO { /** * 是否允许为空 */ - @TableField("case when is_nullable = 'yes' then '1' else '0' end") private Boolean nullable; /** * 是否主键 */ - @TableField("case when column_key = 'PRI' then '1' else '0' end") private Boolean primaryKey; /** * 是否自增 */ - @TableField("case when extra = 'auto_increment' then '1' else '0' end") private Boolean autoIncrement; /** * 排序字段 diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/dataobject/codegen/SchemaTableDO.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/dataobject/db/DatabaseTableDO.java similarity index 56% rename from yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/dataobject/codegen/SchemaTableDO.java rename to yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/dataobject/db/DatabaseTableDO.java index a70753e1a..90ea8529a 100644 --- a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/dataobject/codegen/SchemaTableDO.java +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/dataobject/db/DatabaseTableDO.java @@ -1,6 +1,5 @@ -package cn.iocoder.yudao.module.infra.dal.dataobject.codegen; +package cn.iocoder.yudao.module.infra.dal.dataobject.db; -import com.baomidou.mybatisplus.annotation.TableName; import lombok.Builder; import lombok.Data; @@ -11,15 +10,10 @@ import java.util.Date; * * @author 芋道源码 */ -@TableName(value = "information_schema.tables", autoResultMap = true) @Data @Builder -public class SchemaTableDO { +public class DatabaseTableDO { - /** - * 数据库 - */ - private String tableSchema; /** * 表名称 */ diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/mysql/codegen/SchemaColumnMapper.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/mysql/codegen/SchemaColumnMapper.java deleted file mode 100644 index b31d4aede..000000000 --- a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/mysql/codegen/SchemaColumnMapper.java +++ /dev/null @@ -1,19 +0,0 @@ -package cn.iocoder.yudao.module.infra.dal.mysql.codegen; - -import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; -import cn.iocoder.yudao.module.infra.dal.dataobject.codegen.SchemaColumnDO; -import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; -import org.apache.ibatis.annotations.Mapper; - -import java.util.List; - -@Mapper -public interface SchemaColumnMapper extends BaseMapperX { - - default List selectListByTableName(String tableSchema, String tableName) { - return selectList(new QueryWrapper().eq("table_name", tableName) - .eq("table_schema", tableSchema) - .orderByAsc("ordinal_position")); - } - -} diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/mysql/codegen/SchemaTableMapper.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/mysql/codegen/SchemaTableMapper.java deleted file mode 100644 index 050e48fbd..000000000 --- a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/mysql/codegen/SchemaTableMapper.java +++ /dev/null @@ -1,26 +0,0 @@ -package cn.iocoder.yudao.module.infra.dal.mysql.codegen; - -import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; -import cn.iocoder.yudao.framework.mybatis.core.query.QueryWrapperX; -import cn.iocoder.yudao.module.infra.dal.dataobject.codegen.SchemaTableDO; -import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; -import org.apache.ibatis.annotations.Mapper; - -import java.util.Collection; -import java.util.List; - -@Mapper -public interface SchemaTableMapper extends BaseMapperX { - - default List selectList(Collection tableSchemas, String tableName, String tableComment) { - return selectList(new QueryWrapperX().in("table_schema", tableSchemas) - .likeIfPresent("table_name", tableName) - .likeIfPresent("table_comment", tableComment)); - } - - default SchemaTableDO selectByTableSchemaAndTableName(String tableSchema, String tableName) { - return selectOne(new QueryWrapper().eq("table_schema",tableSchema) - .eq("table_name", tableName)); - } - -} diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/mysql/db/DatabaseTableDAO.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/mysql/db/DatabaseTableDAO.java new file mode 100644 index 000000000..cfc99a653 --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/mysql/db/DatabaseTableDAO.java @@ -0,0 +1,57 @@ +package cn.iocoder.yudao.module.infra.dal.mysql.db; + +import cn.hutool.core.collection.CollUtil; +import cn.iocoder.yudao.module.infra.dal.dataobject.db.DatabaseColumnDO; +import cn.iocoder.yudao.module.infra.dal.dataobject.db.DatabaseTableDO; +import com.baomidou.mybatisplus.annotation.DbType; + +import java.sql.Connection; +import java.util.List; + +/** + * 数据库 Table DAO 接口 + * + * @author 芋道源码 + */ +public interface DatabaseTableDAO { + + /** + * 获得表列表,基于表名称 + 表描述进行模糊匹配 + * + * @param connection 数据库连接 + * @param tableNameLike 表名称,模糊匹配 + * @param tableCommentLike 表描述,模糊匹配 + * @return 表列表 + */ + List selectTableList(Connection connection, String tableNameLike, String tableCommentLike); + + /** + * 获得指定表名 + * + * @param connection 数据库连接 + * @param tableName 表名称 + * @return 表 + */ + default DatabaseTableDO selectTable(Connection connection, String tableName) { + // 考虑到对性能没有要求,直接查询列表,然后内存过滤到记录 + List tables = selectTableList(connection, tableName, null); + return CollUtil.findOne(tables, table -> table.getTableName().equalsIgnoreCase(tableName)); + } + + /** + * 获得指定表的字段列表 + * + * @param connection 数据库连接 + * @param tableName 表名称 + * @return 字段列表 + */ + List selectColumnList(Connection connection, String tableName); + + /** + * 获得数据库的类型 + * + * @return 数据库的类型 + */ + DbType getType(); + +} diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/mysql/db/DatabaseTableMySQLDAOImpl.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/mysql/db/DatabaseTableMySQLDAOImpl.java new file mode 100644 index 000000000..c9d933d96 --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/mysql/db/DatabaseTableMySQLDAOImpl.java @@ -0,0 +1,70 @@ +package cn.iocoder.yudao.module.infra.dal.mysql.db; + +import cn.hutool.core.util.StrUtil; +import cn.iocoder.yudao.framework.mybatis.core.util.JdbcUtils; +import cn.iocoder.yudao.module.infra.dal.dataobject.db.DatabaseColumnDO; +import cn.iocoder.yudao.module.infra.dal.dataobject.db.DatabaseTableDO; +import com.baomidou.mybatisplus.annotation.DbType; +import org.springframework.stereotype.Repository; + +import java.sql.Connection; +import java.util.List; + +/** + * {@link DatabaseTableDAO} 的 MySQL 实现类 + * + * @author 芋道源码 + */ +@Repository +public class DatabaseTableMySQLDAOImpl implements DatabaseTableDAO { + + @Override + public List selectTableList(Connection connection, String tableNameLike, String tableCommentLike) { + // 拼接 SQL + String sql = "SELECT table_name, table_comment, create_time" + + " FROM information_schema.TABLES" + + " WHERE table_schema = (SELECT DATABASE())"; + if (StrUtil.isNotEmpty(tableNameLike)) { + sql += StrUtil.format(" AND table_name LIKE '%{}%'", tableNameLike); + } + if (StrUtil.isNotEmpty(tableCommentLike)) { + sql += StrUtil.format(" AND table_comment LIKE '%{}%'", tableCommentLike); + } + // 执行并返回结果 + return JdbcUtils.query(connection, sql, (rs, rowNum) -> DatabaseTableDO.builder() + .tableName(rs.getString("table_name")) + .tableComment(rs.getString("table_comment")) + .createTime(rs.getDate("create_time")) + .build()); + } + + @Override + public List selectColumnList(Connection connection, String tableName) { + // 拼接 SQL + String sql = "SELECT table_name, column_name, column_type, column_comment, " + + " (CASE WHEN is_nullable = 'yes' THEN '1' ELSE '0' END) AS nullable," + + " (CASE WHEN column_key = 'PRI' THEN '1' ELSE '0' END) AS primary_key," + + " (CASE WHEN extra = 'auto_increment' THEN '1' ELSE '0' END) AS auto_increment," + + " ordinal_position" + + " FROM information_schema.COLUMNS" + + " WHERE table_schema = (SELECT DATABASE())" + + String.format(" AND table_name = '%s'", tableName); + // 执行并返回结果 + return JdbcUtils.query(connection, sql, (rs, rowNum) -> DatabaseColumnDO.builder() + .tableName(rs.getString("table_name")) + .columnName(rs.getString("column_name")) + .columnType(rs.getString("column_type")) + .columnComment(rs.getString("column_comment")) + .nullable(rs.getBoolean("nullable")) + .primaryKey(rs.getBoolean("primary_key")) + .autoIncrement(rs.getBoolean("auto_increment")) + .ordinalPosition(rs.getInt("ordinal_position")) + .build()); + } + + @Override + public DbType getType() { + return DbType.MYSQL; + } + +} diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/codegen/CodegenService.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/codegen/CodegenService.java index c774c88c9..7d3951afa 100644 --- a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/codegen/CodegenService.java +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/codegen/CodegenService.java @@ -5,7 +5,7 @@ import cn.iocoder.yudao.module.infra.controller.admin.codegen.vo.CodegenUpdateRe import cn.iocoder.yudao.module.infra.controller.admin.codegen.vo.table.CodegenTablePageReqVO; import cn.iocoder.yudao.module.infra.dal.dataobject.codegen.CodegenColumnDO; import cn.iocoder.yudao.module.infra.dal.dataobject.codegen.CodegenTableDO; -import cn.iocoder.yudao.module.infra.dal.dataobject.codegen.SchemaTableDO; +import cn.iocoder.yudao.module.infra.dal.dataobject.db.DatabaseTableDO; import java.util.List; import java.util.Map; @@ -119,6 +119,6 @@ public interface CodegenService { * @param tableComment 表描述 * @return 表定义列表 */ - List getSchemaTableList(String tableName, String tableComment); + List getSchemaTableList(String tableName, String tableComment); } diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/codegen/CodegenServiceImpl.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/codegen/CodegenServiceImpl.java index cdf5d3dc7..cdeda9d67 100644 --- a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/codegen/CodegenServiceImpl.java +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/codegen/CodegenServiceImpl.java @@ -8,17 +8,16 @@ import cn.iocoder.yudao.module.infra.controller.admin.codegen.vo.table.CodegenTa import cn.iocoder.yudao.module.infra.convert.codegen.CodegenConvert; import cn.iocoder.yudao.module.infra.dal.dataobject.codegen.CodegenColumnDO; import cn.iocoder.yudao.module.infra.dal.dataobject.codegen.CodegenTableDO; -import cn.iocoder.yudao.module.infra.dal.dataobject.codegen.SchemaColumnDO; -import cn.iocoder.yudao.module.infra.dal.dataobject.codegen.SchemaTableDO; +import cn.iocoder.yudao.module.infra.dal.dataobject.db.DatabaseColumnDO; +import cn.iocoder.yudao.module.infra.dal.dataobject.db.DatabaseTableDO; import cn.iocoder.yudao.module.infra.dal.mysql.codegen.CodegenColumnMapper; import cn.iocoder.yudao.module.infra.dal.mysql.codegen.CodegenTableMapper; -import cn.iocoder.yudao.module.infra.dal.mysql.codegen.SchemaColumnMapper; -import cn.iocoder.yudao.module.infra.dal.mysql.codegen.SchemaTableMapper; import cn.iocoder.yudao.module.infra.enums.codegen.CodegenImportTypeEnum; import cn.iocoder.yudao.module.infra.framework.codegen.config.CodegenProperties; import cn.iocoder.yudao.module.infra.service.codegen.inner.CodegenBuilder; import cn.iocoder.yudao.module.infra.service.codegen.inner.CodegenEngine; import cn.iocoder.yudao.module.infra.service.codegen.inner.CodegenSQLParser; +import cn.iocoder.yudao.module.infra.service.db.DatabaseTableService; import cn.iocoder.yudao.module.system.api.user.AdminUserApi; import org.apache.commons.collections4.KeyValue; import org.springframework.stereotype.Service; @@ -43,9 +42,8 @@ import static cn.iocoder.yudao.module.infra.enums.ErrorCodeConstants.*; public class CodegenServiceImpl implements CodegenService { @Resource - private SchemaTableMapper schemaTableMapper; - @Resource - private SchemaColumnMapper schemaColumnMapper; + private DatabaseTableService databaseTableService; + @Resource private CodegenTableMapper codegenTableMapper; @Resource @@ -63,7 +61,7 @@ public class CodegenServiceImpl implements CodegenService { private CodegenProperties codegenProperties; private Long createCodegen0(Long userId, CodegenImportTypeEnum importType, - SchemaTableDO schemaTable, List schemaColumns) { + DatabaseTableDO schemaTable, List schemaColumns) { // 校验导入的表和字段非空 if (schemaTable == null) { throw exception(CODEGEN_IMPORT_TABLE_NULL); @@ -90,10 +88,10 @@ public class CodegenServiceImpl implements CodegenService { @Override public Long createCodegenListFromSQL(Long userId, String sql) { // 从 SQL 中,获得数据库表结构 - SchemaTableDO schemaTable; - List schemaColumns; + DatabaseTableDO schemaTable; + List schemaColumns; try { - KeyValue> result = CodegenSQLParser.parse(sql); + KeyValue> result = CodegenSQLParser.parse(sql); schemaTable = result.getKey(); schemaColumns = result.getValue(); } catch (Exception ex) { @@ -108,8 +106,8 @@ public class CodegenServiceImpl implements CodegenService { // 获取当前schema String tableSchema = codegenProperties.getDbSchemas().iterator().next(); // 从数据库中,获得数据库表结构 - SchemaTableDO schemaTable = schemaTableMapper.selectByTableSchemaAndTableName(tableSchema, tableName); - List schemaColumns = schemaColumnMapper.selectListByTableName(tableSchema, tableName); + DatabaseTableDO schemaTable = databaseTableService.getTable(0L, tableName); + List schemaColumns = databaseTableService.getColumnList(0L, tableName); // 导入 return this.createCodegen0(userId, CodegenImportTypeEnum.DB, schemaTable, schemaColumns); } @@ -147,9 +145,8 @@ public class CodegenServiceImpl implements CodegenService { if (table == null) { throw exception(CODEGEN_TABLE_NOT_EXISTS); } - String tableSchema = codegenProperties.getDbSchemas().iterator().next(); // 从数据库中,获得数据库表结构 - List schemaColumns = schemaColumnMapper.selectListByTableName(tableSchema, table.getTableName()); + List schemaColumns = databaseTableService.getColumnList(0L, table.getTableName()); // 执行同步 this.syncCodegen0(tableId, schemaColumns); @@ -164,9 +161,9 @@ public class CodegenServiceImpl implements CodegenService { throw exception(CODEGEN_TABLE_NOT_EXISTS); } // 从 SQL 中,获得数据库表结构 - List schemaColumns; + List schemaColumns; try { - KeyValue> result = CodegenSQLParser.parse(sql); + KeyValue> result = CodegenSQLParser.parse(sql); schemaColumns = result.getValue(); } catch (Exception ex) { throw exception(CODEGEN_PARSE_SQL_ERROR); @@ -176,12 +173,12 @@ public class CodegenServiceImpl implements CodegenService { this.syncCodegen0(tableId, schemaColumns); } - private void syncCodegen0(Long tableId, List schemaColumns) { + private void syncCodegen0(Long tableId, List schemaColumns) { // 校验导入的字段不为空 if (CollUtil.isEmpty(schemaColumns)) { throw exception(CODEGEN_SYNC_COLUMNS_NULL); } - Set schemaColumnNames = CollectionUtils.convertSet(schemaColumns, SchemaColumnDO::getColumnName); + Set schemaColumnNames = CollectionUtils.convertSet(schemaColumns, DatabaseColumnDO::getColumnName); // 构建 CodegenColumnDO 数组,只同步新增的字段 List codegenColumns = codegenColumnMapper.selectListByTableId(tableId); @@ -255,8 +252,8 @@ public class CodegenServiceImpl implements CodegenService { } @Override - public List getSchemaTableList(String tableName, String tableComment) { - List tables = schemaTableMapper.selectList(codegenProperties.getDbSchemas(), tableName, tableComment); + public List getSchemaTableList(String tableName, String tableComment) { + List tables = databaseTableService.getTableList(0L, tableName, tableComment); // TODO 强制移除 Quartz 的表,未来做成可配置 tables.removeIf(table -> table.getTableName().startsWith("QRTZ_")); tables.removeIf(table -> table.getTableName().startsWith("ACT_")); diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/codegen/inner/CodegenBuilder.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/codegen/inner/CodegenBuilder.java index fe07df7a7..17ebbf9fe 100644 --- a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/codegen/inner/CodegenBuilder.java +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/codegen/inner/CodegenBuilder.java @@ -7,8 +7,8 @@ import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; import cn.iocoder.yudao.module.infra.convert.codegen.CodegenConvert; import cn.iocoder.yudao.module.infra.dal.dataobject.codegen.CodegenColumnDO; import cn.iocoder.yudao.module.infra.dal.dataobject.codegen.CodegenTableDO; -import cn.iocoder.yudao.module.infra.dal.dataobject.codegen.SchemaColumnDO; -import cn.iocoder.yudao.module.infra.dal.dataobject.codegen.SchemaTableDO; +import cn.iocoder.yudao.module.infra.dal.dataobject.db.DatabaseColumnDO; +import cn.iocoder.yudao.module.infra.dal.dataobject.db.DatabaseTableDO; import cn.iocoder.yudao.module.infra.enums.codegen.CodegenColumnHtmlTypeEnum; import cn.iocoder.yudao.module.infra.enums.codegen.CodegenColumnListConditionEnum; import cn.iocoder.yudao.module.infra.enums.codegen.CodegenTemplateTypeEnum; @@ -22,8 +22,8 @@ import static cn.hutool.core.text.CharSequenceUtil.*; /** * 代码生成器的 Builder,负责: - * 1. 将数据库的表 {@link SchemaTableDO} 定义,构建成 {@link CodegenTableDO} - * 2. 将数据库的列 {@link SchemaColumnDO} 构定义,建成 {@link CodegenColumnDO} + * 1. 将数据库的表 {@link DatabaseTableDO} 定义,构建成 {@link CodegenTableDO} + * 2. 将数据库的列 {@link DatabaseColumnDO} 构定义,建成 {@link CodegenColumnDO} */ @Component public class CodegenBuilder { @@ -109,7 +109,7 @@ public class CodegenBuilder { LIST_OPERATION_RESULT_EXCLUDE_COLUMN.remove("createTime"); // 创建时间,还是需要返回的 } - public CodegenTableDO buildTable(SchemaTableDO schemaTable) { + public CodegenTableDO buildTable(DatabaseTableDO schemaTable) { CodegenTableDO table = CodegenConvert.INSTANCE.convert(schemaTable); initTableDefault(table); return table; @@ -133,7 +133,7 @@ public class CodegenBuilder { table.setTemplateType(CodegenTemplateTypeEnum.CRUD.getType()); } - public List buildColumns(Long tableId, List schemaColumns) { + public List buildColumns(Long tableId, List schemaColumns) { List columns = CodegenConvert.INSTANCE.convertList(schemaColumns); for (CodegenColumnDO column : columns) { column.setTableId(tableId); diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/codegen/inner/CodegenSQLParser.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/codegen/inner/CodegenSQLParser.java index 016a1dbc5..0438cda25 100644 --- a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/codegen/inner/CodegenSQLParser.java +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/codegen/inner/CodegenSQLParser.java @@ -1,8 +1,8 @@ package cn.iocoder.yudao.module.infra.service.codegen.inner; import cn.hutool.core.collection.CollUtil; -import cn.iocoder.yudao.module.infra.dal.dataobject.codegen.SchemaColumnDO; -import cn.iocoder.yudao.module.infra.dal.dataobject.codegen.SchemaTableDO; +import cn.iocoder.yudao.module.infra.dal.dataobject.db.DatabaseColumnDO; +import cn.iocoder.yudao.module.infra.dal.dataobject.db.DatabaseTableDO; import com.alibaba.druid.DbType; import com.alibaba.druid.sql.ast.expr.SQLCharExpr; import com.alibaba.druid.sql.ast.statement.SQLColumnDefinition; @@ -21,7 +21,7 @@ import java.util.Objects; import static com.alibaba.druid.sql.SQLUtils.normalize; /** - * SQL 解析器,将创建表的 SQL,解析成 {@link SchemaTableDO} 和 {@link SchemaColumnDO} 对象, + * SQL 解析器,将创建表的 SQL,解析成 {@link DatabaseTableDO} 和 {@link DatabaseColumnDO} 对象, * 后续可以基于它们,生成代码~ * * @author 芋道源码 @@ -29,18 +29,18 @@ import static com.alibaba.druid.sql.SQLUtils.normalize; public class CodegenSQLParser { /** - * 解析建表 SQL 语句,返回 {@link SchemaTableDO} 和 {@link SchemaColumnDO} 对象 + * 解析建表 SQL 语句,返回 {@link DatabaseTableDO} 和 {@link DatabaseColumnDO} 对象 * * @param sql 建表 SQL 语句 * @return 解析结果 */ - public static KeyValue> parse(String sql) { + public static KeyValue> parse(String sql) { // 解析 SQL 成 Statement SQLCreateTableStatement statement = parseCreateSQL(sql); // 解析 Table 表 - SchemaTableDO table = parseTable(statement); + DatabaseTableDO table = parseTable(statement); // 解析 Column 字段 - List columns = parseColumns(statement); + List columns = parseColumns(statement); columns.forEach(column -> column.setTableName(table.getTableName())); // 返回 return new DefaultKeyValue<>(table, columns); @@ -61,8 +61,8 @@ public class CodegenSQLParser { return (MySqlCreateTableStatement) repository.findTable(tableName).getStatement(); } - private static SchemaTableDO parseTable(SQLCreateTableStatement statement) { - return SchemaTableDO.builder() + private static DatabaseTableDO parseTable(SQLCreateTableStatement statement) { + return DatabaseTableDO.builder() .tableName(statement.getTableSource().getTableName(true)) .tableComment(getCommentText(statement)) .build(); @@ -75,13 +75,13 @@ public class CodegenSQLParser { return ((SQLCharExpr) statement.getComment()).getText(); } - private static List parseColumns(SQLCreateTableStatement statement) { - List columns = new ArrayList<>(); + private static List parseColumns(SQLCreateTableStatement statement) { + List columns = new ArrayList<>(); statement.getTableElementList().forEach(element -> parseColumn(columns, element)); return columns; } - private static void parseColumn(List columns, SQLTableElement element) { + private static void parseColumn(List columns, SQLTableElement element) { // 处理主键 if (element instanceof SQLPrimaryKey) { parsePrimaryKey(columns, (SQLPrimaryKey) element); @@ -93,16 +93,16 @@ public class CodegenSQLParser { } } - private static void parsePrimaryKey(List columns, SQLPrimaryKey primaryKey) { + private static void parsePrimaryKey(List columns, SQLPrimaryKey primaryKey) { String columnName = normalize(primaryKey.getColumns().get(0).toString()); // 暂时不考虑联合主键 // 匹配 columns 主键字段,设置为 primary columns.stream().filter(column -> column.getColumnName().equals(columnName)) .forEach(column -> column.setPrimaryKey(true)); } - private static void parseColumnDefinition(List columns, SQLColumnDefinition definition) { + private static void parseColumnDefinition(List columns, SQLColumnDefinition definition) { String text = definition.toString().toUpperCase(); - columns.add(SchemaColumnDO.builder() + columns.add(DatabaseColumnDO.builder() .columnName(normalize(definition.getColumnName())) .columnType(definition.getDataType().toString()) .columnComment(Objects.isNull(definition.getComment()) ? "" diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/db/DataSourceConfigService.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/db/DataSourceConfigService.java index b5e9e21ee..e7b2d9c5f 100755 --- a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/db/DataSourceConfigService.java +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/db/DataSourceConfigService.java @@ -1,10 +1,9 @@ package cn.iocoder.yudao.module.infra.service.db; -import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.module.infra.controller.admin.db.vo.DataSourceConfigCreateReqVO; import cn.iocoder.yudao.module.infra.controller.admin.db.vo.DataSourceConfigUpdateReqVO; import cn.iocoder.yudao.module.infra.dal.dataobject.db.DataSourceConfigDO; -import org.w3c.dom.stylesheets.LinkStyle; +import cn.iocoder.yudao.module.infra.dal.dataobject.db.DatabaseTableDO; import javax.validation.Valid; import java.util.List; diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/db/DataSourceConfigServiceImpl.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/db/DataSourceConfigServiceImpl.java index e2f1a6559..e591f259a 100755 --- a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/db/DataSourceConfigServiceImpl.java +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/db/DataSourceConfigServiceImpl.java @@ -1,22 +1,21 @@ package cn.iocoder.yudao.module.infra.service.db; -import cn.hutool.db.DbUtil; -import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.framework.mybatis.core.util.DatabaseUtils; +import cn.iocoder.yudao.framework.mybatis.core.util.JdbcUtils; import cn.iocoder.yudao.module.infra.controller.admin.db.vo.DataSourceConfigCreateReqVO; import cn.iocoder.yudao.module.infra.controller.admin.db.vo.DataSourceConfigUpdateReqVO; import cn.iocoder.yudao.module.infra.convert.db.DataSourceConfigConvert; import cn.iocoder.yudao.module.infra.dal.dataobject.db.DataSourceConfigDO; import cn.iocoder.yudao.module.infra.dal.mysql.db.DataSourceConfigMapper; -import com.baomidou.mybatisplus.extension.toolkit.JdbcUtils; +import com.baomidou.dynamic.datasource.spring.boot.autoconfigure.DataSourceProperty; +import com.baomidou.dynamic.datasource.spring.boot.autoconfigure.DynamicDataSourceProperties; import org.jasypt.encryption.StringEncryptor; import org.springframework.stereotype.Service; import org.springframework.validation.annotation.Validated; import javax.annotation.Resource; -import java.sql.Connection; import java.util.List; +import java.util.Objects; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; import static cn.iocoder.yudao.module.infra.enums.ErrorCodeConstants.DATA_SOURCE_CONFIG_NOT_EXISTS; @@ -37,6 +36,9 @@ public class DataSourceConfigServiceImpl implements DataSourceConfigService { @Resource private StringEncryptor stringEncryptor; + @Resource + private DynamicDataSourceProperties dynamicDataSourceProperties; + @Override public Long createDataSourceConfig(DataSourceConfigCreateReqVO createReqVO) { DataSourceConfigDO dataSourceConfig = DataSourceConfigConvert.INSTANCE.convert(createReqVO); @@ -77,6 +79,11 @@ public class DataSourceConfigServiceImpl implements DataSourceConfigService { @Override public DataSourceConfigDO getDataSourceConfig(Long id) { + // 如果 id 为 0,默认为 master 的数据源 + if (Objects.equals(id, DataSourceConfigDO.ID_MASTER)) { + return buildMasterDataSourceConfig(); + } + // 从 DB 中读取 DataSourceConfigDO dataSourceConfig = dataSourceConfigMapper.selectById(id); dataSourceConfig.setPassword(stringEncryptor.decrypt(dataSourceConfig.getPassword())); return dataSourceConfig; @@ -84,14 +91,26 @@ public class DataSourceConfigServiceImpl implements DataSourceConfigService { @Override public List getDataSourceConfigList() { - return dataSourceConfigMapper.selectList(); + List result = dataSourceConfigMapper.selectList(); + // 补充 master 数据源 + result.add(0, buildMasterDataSourceConfig()); + return result; } private void checkConnectionOK(DataSourceConfigDO config) { - boolean success = DatabaseUtils.isConnectionOK(config.getUrl(), config.getUsername(), config.getPassword()); + boolean success = JdbcUtils.isConnectionOK(config.getUrl(), config.getUsername(), config.getPassword()); if (!success) { throw exception(DATA_SOURCE_CONFIG_NOT_OK); } } + private DataSourceConfigDO buildMasterDataSourceConfig() { + String primary = dynamicDataSourceProperties.getPrimary(); + DataSourceProperty dataSourceProperty = dynamicDataSourceProperties.getDatasource().get(primary); + return new DataSourceConfigDO().setId(DataSourceConfigDO.ID_MASTER).setName(primary) + .setUrl(dataSourceProperty.getUrl()) + .setUsername(dataSourceProperty.getUsername()) + .setPassword(dataSourceProperty.getPassword()); + } + } diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/db/DatabaseTableService.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/db/DatabaseTableService.java new file mode 100644 index 000000000..426d88639 --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/db/DatabaseTableService.java @@ -0,0 +1,43 @@ +package cn.iocoder.yudao.module.infra.service.db; + +import cn.iocoder.yudao.module.infra.dal.dataobject.db.DatabaseColumnDO; +import cn.iocoder.yudao.module.infra.dal.dataobject.db.DatabaseTableDO; + +import java.util.List; + +/** + * 数据库表 Service + * + * @author 芋道源码 + */ +public interface DatabaseTableService { + + /** + * 获得表列表,基于表名称 + 表描述进行模糊匹配 + * + * @param dataSourceConfigId 数据源配置的编号 + * @param tableNameLike 表名称,模糊匹配 + * @param tableCommentLike 表描述,模糊匹配 + * @return 表列表 + */ + List getTableList(Long dataSourceConfigId, String tableNameLike, String tableCommentLike); + + /** + * 获得指定表名 + * + * @param dataSourceConfigId 数据源配置的编号 + * @param tableName 表名称 + * @return 表 + */ + DatabaseTableDO getTable(Long dataSourceConfigId, String tableName); + + /** + * 获得指定表的字段列表 + * + * @param dataSourceConfigId 数据源配置的编号 + * @param tableName 表名称 + * @return 字段列表 + */ + List getColumnList(Long dataSourceConfigId, String tableName); + +} diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/db/DatabaseTableServiceImpl.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/db/DatabaseTableServiceImpl.java new file mode 100644 index 000000000..234e6d4a6 --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/db/DatabaseTableServiceImpl.java @@ -0,0 +1,74 @@ +package cn.iocoder.yudao.module.infra.service.db; + +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.lang.Assert; +import cn.iocoder.yudao.framework.mybatis.core.util.JdbcUtils; +import cn.iocoder.yudao.module.infra.dal.dataobject.db.DataSourceConfigDO; +import cn.iocoder.yudao.module.infra.dal.dataobject.db.DatabaseColumnDO; +import cn.iocoder.yudao.module.infra.dal.dataobject.db.DatabaseTableDO; +import cn.iocoder.yudao.module.infra.dal.mysql.db.DatabaseTableDAO; +import com.baomidou.mybatisplus.annotation.DbType; +import lombok.SneakyThrows; +import org.springframework.stereotype.Service; + +import javax.annotation.Resource; +import java.sql.Connection; +import java.util.List; + +/** + * 数据库表 Service 实现类 + * + * @author 芋道源码 + */ +@Service +public class DatabaseTableServiceImpl implements DatabaseTableService { + + @Resource + private DataSourceConfigService dataSourceConfigService; + + @Resource + private List databaseTableDAOs; + + @Override + @SneakyThrows + public List getTableList(Long dataSourceConfigId, String tableNameLike, String tableCommentLike) { + try (Connection connection = getConnection(dataSourceConfigId)) { + return getDatabaseTableDAO(dataSourceConfigId).selectTableList(connection, tableNameLike, tableCommentLike); + } + } + + @Override + @SneakyThrows + public DatabaseTableDO getTable(Long dataSourceConfigId, String tableName) { + try (Connection connection = getConnection(dataSourceConfigId)) { + return getDatabaseTableDAO(dataSourceConfigId).selectTable(connection, tableName); + } + } + + @Override + @SneakyThrows + public List getColumnList(Long dataSourceConfigId, String tableName) { + try (Connection connection = getConnection(dataSourceConfigId)) { + return getDatabaseTableDAO(dataSourceConfigId).selectColumnList(connection, tableName); + } + } + + private Connection getConnection(Long dataSourceConfigId) { + DataSourceConfigDO config = dataSourceConfigService.getDataSourceConfig(dataSourceConfigId); + Assert.notNull(config, "数据源({}) 不存在!", dataSourceConfigId); + return JdbcUtils.getConnection(config.getUrl(), config.getUsername(), config.getPassword()); + } + + private DatabaseTableDAO getDatabaseTableDAO(Long dataSourceConfigId) { + DataSourceConfigDO config = dataSourceConfigService.getDataSourceConfig(dataSourceConfigId); + Assert.notNull(config, "数据源({}) 不存在!", dataSourceConfigId); + // 获得 dbType + DbType dbType = JdbcUtils.getDbType(config.getUrl()); + Assert.notNull(config, "数据源类型({}) 不存在!", config.getUrl()); + // 获得 DatabaseTableDAO + DatabaseTableDAO dao = CollUtil.findOne(databaseTableDAOs, databaseTableDAO -> databaseTableDAO.getType().equals(dbType)); + Assert.notNull(dao, "DAO({}) 查找不到实现!", dbType); + return dao; + } + +} diff --git a/yudao-module-infra/yudao-module-infra-biz/src/test/java/cn/iocoder/yudao/module/infra/service/db/DataSourceConfigServiceImplTest.java b/yudao-module-infra/yudao-module-infra-biz/src/test/java/cn/iocoder/yudao/module/infra/service/db/DataSourceConfigServiceImplTest.java index 5c51b198e..583730cde 100755 --- a/yudao-module-infra/yudao-module-infra-biz/src/test/java/cn/iocoder/yudao/module/infra/service/db/DataSourceConfigServiceImplTest.java +++ b/yudao-module-infra/yudao-module-infra-biz/src/test/java/cn/iocoder/yudao/module/infra/service/db/DataSourceConfigServiceImplTest.java @@ -1,6 +1,6 @@ package cn.iocoder.yudao.module.infra.service.db; -import cn.iocoder.yudao.framework.mybatis.core.util.DatabaseUtils; +import cn.iocoder.yudao.framework.mybatis.core.util.JdbcUtils; import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest; import cn.iocoder.yudao.module.infra.controller.admin.db.vo.DataSourceConfigCreateReqVO; import cn.iocoder.yudao.module.infra.controller.admin.db.vo.DataSourceConfigUpdateReqVO; @@ -41,12 +41,12 @@ public class DataSourceConfigServiceImplTest extends BaseDbUnitTest { @Test public void testCreateDataSourceConfig_success() { - try (MockedStatic databaseUtilsMock = mockStatic(DatabaseUtils.class)) { + try (MockedStatic databaseUtilsMock = mockStatic(JdbcUtils.class)) { // 准备参数 DataSourceConfigCreateReqVO reqVO = randomPojo(DataSourceConfigCreateReqVO.class); // mock 方法 when(stringEncryptor.encrypt(eq(reqVO.getPassword()))).thenReturn("123456"); - databaseUtilsMock.when(() -> DatabaseUtils.isConnectionOK(eq(reqVO.getUrl()), + databaseUtilsMock.when(() -> JdbcUtils.isConnectionOK(eq(reqVO.getUrl()), eq(reqVO.getUsername()), eq(reqVO.getPassword()))).thenReturn(true); // 调用 @@ -62,7 +62,7 @@ public class DataSourceConfigServiceImplTest extends BaseDbUnitTest { @Test public void testUpdateDataSourceConfig_success() { - try (MockedStatic databaseUtilsMock = mockStatic(DatabaseUtils.class)) { + try (MockedStatic databaseUtilsMock = mockStatic(JdbcUtils.class)) { // mock 数据 DataSourceConfigDO dbDataSourceConfig = randomPojo(DataSourceConfigDO.class); dataSourceConfigMapper.insert(dbDataSourceConfig);// @Sql: 先插入出一条存在的数据 @@ -72,7 +72,7 @@ public class DataSourceConfigServiceImplTest extends BaseDbUnitTest { }); // mock 方法 when(stringEncryptor.encrypt(eq(reqVO.getPassword()))).thenReturn("123456"); - databaseUtilsMock.when(() -> DatabaseUtils.isConnectionOK(eq(reqVO.getUrl()), + databaseUtilsMock.when(() -> JdbcUtils.isConnectionOK(eq(reqVO.getUrl()), eq(reqVO.getUsername()), eq(reqVO.getPassword()))).thenReturn(true); // 调用