Ver código fonte

优化代码生成器实现,增加 DatabaseTableDAO 抽象,支持多 db 类型

YunaiV 3 anos atrás
pai
commit
d79549b48a
21 arquivos alterados com 419 adições e 155 exclusões
  1. 0 29
      yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/mybatis/core/util/DatabaseUtils.java
  2. 85 0
      yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/mybatis/core/util/JdbcUtils.java
  3. 2 2
      yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/codegen/CodegenController.java
  4. 6 6
      yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/convert/codegen/CodegenConvert.java
  5. 0 1
      yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/dataobject/codegen/CodegenColumnDO.java
  6. 5 0
      yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/dataobject/db/DataSourceConfigDO.java
  7. 2 6
      yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/dataobject/db/DatabaseColumnDO.java
  8. 2 8
      yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/dataobject/db/DatabaseTableDO.java
  9. 0 19
      yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/mysql/codegen/SchemaColumnMapper.java
  10. 0 26
      yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/mysql/codegen/SchemaTableMapper.java
  11. 57 0
      yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/mysql/db/DatabaseTableDAO.java
  12. 70 0
      yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/mysql/db/DatabaseTableMySQLDAOImpl.java
  13. 2 2
      yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/codegen/CodegenService.java
  14. 18 21
      yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/codegen/CodegenServiceImpl.java
  15. 6 6
      yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/codegen/inner/CodegenBuilder.java
  16. 15 15
      yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/codegen/inner/CodegenSQLParser.java
  17. 1 2
      yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/db/DataSourceConfigService.java
  18. 26 7
      yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/db/DataSourceConfigServiceImpl.java
  19. 43 0
      yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/db/DatabaseTableService.java
  20. 74 0
      yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/db/DatabaseTableServiceImpl.java
  21. 5 5
      yudao-module-infra/yudao-module-infra-biz/src/test/java/cn/iocoder/yudao/module/infra/service/db/DataSourceConfigServiceImplTest.java

+ 0 - 29
yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/mybatis/core/util/DatabaseUtils.java

@@ -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;
-        }
-    }
-
-}

+ 85 - 0
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 <T> List<T> query(Connection connection, String sql, RowMapper<T> handler) {
+        try (PreparedStatement ps = connection.prepareStatement(sql);
+             ResultSet rs = ps.executeQuery()) {
+            // 处理结果
+            List<T> 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);
+    }
+
+}

+ 2 - 2
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<SchemaTableDO> schemaTables = codegenService.getSchemaTableList(tableName, tableComment);
+        List<DatabaseTableDO> schemaTables = codegenService.getSchemaTableList(tableName, tableComment);
         // 移除在 Codegen 中,已经存在的
         Set<String> existsTables = CollectionUtils.convertSet(codegenService.getCodeGenTableList(), CodegenTableDO::getTableName);
         schemaTables.removeIf(table -> existsTables.contains(table.getTableName()));

+ 6 - 6
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<CodegenColumnDO> convertList(List<SchemaColumnDO> list);
+    List<CodegenColumnDO> convertList(List<DatabaseColumnDO> list);
 
-    CodegenTableRespVO convert(SchemaColumnDO bean);
+    CodegenTableRespVO convert(DatabaseColumnDO bean);
 
     // ========== CodegenTableDO 相关 ==========
 
@@ -47,7 +47,7 @@ public interface CodegenConvert {
 
     List<CodegenColumnDO> convertList03(List<CodegenUpdateReqVO.Column> columns);
 
-    List<SchemaTableRespVO> convertList04(List<SchemaTableDO> list);
+    List<SchemaTableRespVO> convertList04(List<DatabaseTableDO> list);
 
     // ========== 其它 ==========
 

+ 0 - 1
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;
     /**
      * 字典类型

+ 5 - 0
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;
+
     /**
      * 主键编号
      */

+ 2 - 6
yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/dataobject/codegen/SchemaColumnDO.java → 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;
     /**
      * 排序字段

+ 2 - 8
yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/dataobject/codegen/SchemaTableDO.java → 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;
     /**
      * 表名称
      */

+ 0 - 19
yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/mysql/codegen/SchemaColumnMapper.java

@@ -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<SchemaColumnDO> {
-
-    default List<SchemaColumnDO> selectListByTableName(String tableSchema, String tableName) {
-        return selectList(new QueryWrapper<SchemaColumnDO>().eq("table_name", tableName)
-                .eq("table_schema", tableSchema)
-                .orderByAsc("ordinal_position"));
-    }
-
-}

+ 0 - 26
yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/mysql/codegen/SchemaTableMapper.java

@@ -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<SchemaTableDO> {
-
-    default List<SchemaTableDO> selectList(Collection<String> tableSchemas, String tableName, String tableComment) {
-        return selectList(new QueryWrapperX<SchemaTableDO>().in("table_schema", tableSchemas)
-                .likeIfPresent("table_name", tableName)
-                .likeIfPresent("table_comment", tableComment));
-    }
-
-    default SchemaTableDO selectByTableSchemaAndTableName(String tableSchema, String tableName) {
-        return selectOne(new QueryWrapper<SchemaTableDO>().eq("table_schema",tableSchema)
-                        .eq("table_name", tableName));
-    }
-
-}

+ 57 - 0
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<DatabaseTableDO> selectTableList(Connection connection, String tableNameLike, String tableCommentLike);
+
+    /**
+     * 获得指定表名
+     *
+     * @param connection 数据库连接
+     * @param tableName 表名称
+     * @return 表
+     */
+    default DatabaseTableDO selectTable(Connection connection, String tableName) {
+        // 考虑到对性能没有要求,直接查询列表,然后内存过滤到记录
+        List<DatabaseTableDO> tables = selectTableList(connection, tableName, null);
+        return CollUtil.findOne(tables, table -> table.getTableName().equalsIgnoreCase(tableName));
+    }
+
+    /**
+     * 获得指定表的字段列表
+     *
+     * @param connection 数据库连接
+     * @param tableName 表名称
+     * @return 字段列表
+     */
+    List<DatabaseColumnDO> selectColumnList(Connection connection, String tableName);
+
+    /**
+     * 获得数据库的类型
+     *
+     * @return 数据库的类型
+     */
+    DbType getType();
+
+}

+ 70 - 0
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<DatabaseTableDO> 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<DatabaseColumnDO> 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;
+    }
+
+}

+ 2 - 2
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<SchemaTableDO> getSchemaTableList(String tableName, String tableComment);
+    List<DatabaseTableDO> getSchemaTableList(String tableName, String tableComment);
 
 }

+ 18 - 21
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<SchemaColumnDO> schemaColumns) {
+                                DatabaseTableDO schemaTable, List<DatabaseColumnDO> 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<SchemaColumnDO> schemaColumns;
+        DatabaseTableDO schemaTable;
+        List<DatabaseColumnDO> schemaColumns;
         try {
-            KeyValue<SchemaTableDO, List<SchemaColumnDO>> result = CodegenSQLParser.parse(sql);
+            KeyValue<DatabaseTableDO, List<DatabaseColumnDO>> 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<SchemaColumnDO> schemaColumns = schemaColumnMapper.selectListByTableName(tableSchema, tableName);
+        DatabaseTableDO schemaTable = databaseTableService.getTable(0L, tableName);
+        List<DatabaseColumnDO> 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<SchemaColumnDO> schemaColumns = schemaColumnMapper.selectListByTableName(tableSchema, table.getTableName());
+        List<DatabaseColumnDO> 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<SchemaColumnDO> schemaColumns;
+        List<DatabaseColumnDO> schemaColumns;
         try {
-            KeyValue<SchemaTableDO, List<SchemaColumnDO>> result = CodegenSQLParser.parse(sql);
+            KeyValue<DatabaseTableDO, List<DatabaseColumnDO>> 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<SchemaColumnDO> schemaColumns) {
+    private void syncCodegen0(Long tableId, List<DatabaseColumnDO> schemaColumns) {
         // 校验导入的字段不为空
         if (CollUtil.isEmpty(schemaColumns)) {
             throw exception(CODEGEN_SYNC_COLUMNS_NULL);
         }
-        Set<String> schemaColumnNames = CollectionUtils.convertSet(schemaColumns, SchemaColumnDO::getColumnName);
+        Set<String> schemaColumnNames = CollectionUtils.convertSet(schemaColumns, DatabaseColumnDO::getColumnName);
 
         // 构建 CodegenColumnDO 数组,只同步新增的字段
         List<CodegenColumnDO> codegenColumns = codegenColumnMapper.selectListByTableId(tableId);
@@ -255,8 +252,8 @@ public class CodegenServiceImpl implements CodegenService {
     }
 
     @Override
-    public List<SchemaTableDO> getSchemaTableList(String tableName, String tableComment) {
-        List<SchemaTableDO> tables = schemaTableMapper.selectList(codegenProperties.getDbSchemas(), tableName, tableComment);
+    public List<DatabaseTableDO> getSchemaTableList(String tableName, String tableComment) {
+        List<DatabaseTableDO> tables = databaseTableService.getTableList(0L, tableName, tableComment);
         // TODO 强制移除 Quartz 的表,未来做成可配置
         tables.removeIf(table -> table.getTableName().startsWith("QRTZ_"));
         tables.removeIf(table -> table.getTableName().startsWith("ACT_"));

+ 6 - 6
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<CodegenColumnDO> buildColumns(Long tableId, List<SchemaColumnDO> schemaColumns) {
+    public List<CodegenColumnDO> buildColumns(Long tableId, List<DatabaseColumnDO> schemaColumns) {
         List<CodegenColumnDO> columns = CodegenConvert.INSTANCE.convertList(schemaColumns);
         for (CodegenColumnDO column : columns) {
             column.setTableId(tableId);

+ 15 - 15
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<SchemaTableDO, List<SchemaColumnDO>> parse(String sql) {
+    public static KeyValue<DatabaseTableDO, List<DatabaseColumnDO>> parse(String sql) {
         // 解析 SQL 成 Statement
         SQLCreateTableStatement statement = parseCreateSQL(sql);
         // 解析 Table 表
-        SchemaTableDO table = parseTable(statement);
+        DatabaseTableDO table = parseTable(statement);
         // 解析 Column 字段
-        List<SchemaColumnDO> columns = parseColumns(statement);
+        List<DatabaseColumnDO> 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<SchemaColumnDO> parseColumns(SQLCreateTableStatement statement) {
-        List<SchemaColumnDO> columns = new ArrayList<>();
+    private static List<DatabaseColumnDO> parseColumns(SQLCreateTableStatement statement) {
+        List<DatabaseColumnDO> columns = new ArrayList<>();
         statement.getTableElementList().forEach(element -> parseColumn(columns, element));
         return columns;
     }
 
-    private static void parseColumn(List<SchemaColumnDO> columns, SQLTableElement element) {
+    private static void parseColumn(List<DatabaseColumnDO> columns, SQLTableElement element) {
         // 处理主键
         if (element instanceof SQLPrimaryKey) {
             parsePrimaryKey(columns, (SQLPrimaryKey) element);
@@ -93,16 +93,16 @@ public class CodegenSQLParser {
         }
     }
 
-    private static void parsePrimaryKey(List<SchemaColumnDO> columns, SQLPrimaryKey primaryKey) {
+    private static void parsePrimaryKey(List<DatabaseColumnDO> 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<SchemaColumnDO> columns, SQLColumnDefinition definition) {
+    private static void parseColumnDefinition(List<DatabaseColumnDO> 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()) ? ""

+ 1 - 2
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;

+ 26 - 7
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<DataSourceConfigDO> getDataSourceConfigList() {
-        return dataSourceConfigMapper.selectList();
+        List<DataSourceConfigDO> 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());
+    }
+
 }

+ 43 - 0
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<DatabaseTableDO> getTableList(Long dataSourceConfigId, String tableNameLike, String tableCommentLike);
+
+    /**
+     * 获得指定表名
+     *
+     * @param dataSourceConfigId 数据源配置的编号
+     * @param tableName 表名称
+     * @return 表
+     */
+    DatabaseTableDO getTable(Long dataSourceConfigId, String tableName);
+
+    /**
+     * 获得指定表的字段列表
+     *
+     * @param dataSourceConfigId 数据源配置的编号
+     * @param tableName 表名称
+     * @return 字段列表
+     */
+    List<DatabaseColumnDO> getColumnList(Long dataSourceConfigId, String tableName);
+
+}

+ 74 - 0
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<DatabaseTableDAO> databaseTableDAOs;
+
+    @Override
+    @SneakyThrows
+    public List<DatabaseTableDO> 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<DatabaseColumnDO> 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;
+    }
+
+}

+ 5 - 5
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<DatabaseUtils> databaseUtilsMock = mockStatic(DatabaseUtils.class)) {
+        try (MockedStatic<JdbcUtils> 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<DatabaseUtils> databaseUtilsMock = mockStatic(DatabaseUtils.class)) {
+        try (MockedStatic<JdbcUtils> 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);
 
             // 调用