Commit d79549b48a635c856f8b8c26b1d2155f56163096

Authored by YunaiV
1 parent d04271b9

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

Showing 21 changed files with 419 additions and 155 deletions
yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/mybatis/core/util/DatabaseUtils.java deleted
1 -package cn.iocoder.yudao.framework.mybatis.core.util;  
2 -  
3 -import java.sql.Connection;  
4 -import java.sql.DriverManager;  
5 -  
6 -/**  
7 - * 数据库工具类  
8 - *  
9 - * @author 芋道源码  
10 - */  
11 -public class DatabaseUtils {  
12 -  
13 - /**  
14 - * 判断连接是否正确  
15 - *  
16 - * @param url 数据源连接  
17 - * @param username 账号  
18 - * @param password 密码  
19 - * @return 是否正确  
20 - */  
21 - public static boolean isConnectionOK(String url, String username, String password) {  
22 - try (Connection ignored = DriverManager.getConnection(url, username, password)) {  
23 - return true;  
24 - } catch (Exception ex) {  
25 - return false;  
26 - }  
27 - }  
28 -  
29 -}  
yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/mybatis/core/util/JdbcUtils.java 0 → 100644
  1 +package cn.iocoder.yudao.framework.mybatis.core.util;
  2 +
  3 +import com.baomidou.mybatisplus.annotation.DbType;
  4 +import lombok.SneakyThrows;
  5 +import org.springframework.dao.DataAccessException;
  6 +import org.springframework.jdbc.core.JdbcTemplate;
  7 +import org.springframework.jdbc.core.RowCallbackHandler;
  8 +import org.springframework.jdbc.core.RowMapper;
  9 +
  10 +import java.sql.*;
  11 +import java.util.ArrayList;
  12 +import java.util.List;
  13 +
  14 +/**
  15 + * JDBC 工具类
  16 + *
  17 + * @author 芋道源码
  18 + */
  19 +public class JdbcUtils {
  20 +
  21 + /**
  22 + * 判断连接是否正确
  23 + *
  24 + * @param url 数据源连接
  25 + * @param username 账号
  26 + * @param password 密码
  27 + * @return 是否正确
  28 + */
  29 + public static boolean isConnectionOK(String url, String username, String password) {
  30 + try (Connection ignored = DriverManager.getConnection(url, username, password)) {
  31 + return true;
  32 + } catch (Exception ex) {
  33 + return false;
  34 + }
  35 + }
  36 +
  37 + /**
  38 + * 获得连接
  39 + *
  40 + * @param url 数据源连接
  41 + * @param username 账号
  42 + * @param password 密码
  43 + * @return 是否正确
  44 + */
  45 + @SneakyThrows
  46 + public static Connection getConnection(String url, String username, String password) {
  47 + return DriverManager.getConnection(url, username, password);
  48 + }
  49 +
  50 + /**
  51 + * 执行指定 SQL,返回查询列表
  52 + *
  53 + * 参考 {@link JdbcTemplate#query(String, RowMapper)} 实现,主要考虑 JdbcTemplate 不支持使用指定 Connection 查询
  54 + *
  55 + * @param connection 数据库连接
  56 + * @param sql SQL
  57 + * @param handler 行处理器
  58 + * @return 列表
  59 + */
  60 + @SneakyThrows
  61 + public static <T> List<T> query(Connection connection, String sql, RowMapper<T> handler) {
  62 + try (PreparedStatement ps = connection.prepareStatement(sql);
  63 + ResultSet rs = ps.executeQuery()) {
  64 + // 处理结果
  65 + List<T> result = new ArrayList<>();
  66 + int rowNum = 0;
  67 + while (rs.next()) {
  68 + result.add(handler.mapRow(rs, rowNum++));
  69 + }
  70 + return result;
  71 + }
  72 + }
  73 +
  74 + /**
  75 + * 获得 URL 对应的 DB 类型
  76 + *
  77 + * @param url URL
  78 + * @return DB 类型
  79 + */
  80 + public static DbType getDbType(String url) {
  81 + String name = com.alibaba.druid.util.JdbcUtils.getDbType(url, null);
  82 + return DbType.getDbType(name);
  83 + }
  84 +
  85 +}
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 @@ -13,7 +13,7 @@ import cn.iocoder.yudao.module.infra.controller.admin.codegen.vo.table.SchemaTab
13 import cn.iocoder.yudao.module.infra.convert.codegen.CodegenConvert; 13 import cn.iocoder.yudao.module.infra.convert.codegen.CodegenConvert;
14 import cn.iocoder.yudao.module.infra.dal.dataobject.codegen.CodegenColumnDO; 14 import cn.iocoder.yudao.module.infra.dal.dataobject.codegen.CodegenColumnDO;
15 import cn.iocoder.yudao.module.infra.dal.dataobject.codegen.CodegenTableDO; 15 import cn.iocoder.yudao.module.infra.dal.dataobject.codegen.CodegenTableDO;
16 -import cn.iocoder.yudao.module.infra.dal.dataobject.codegen.SchemaTableDO; 16 +import cn.iocoder.yudao.module.infra.dal.dataobject.db.DatabaseTableDO;
17 import cn.iocoder.yudao.module.infra.service.codegen.CodegenService; 17 import cn.iocoder.yudao.module.infra.service.codegen.CodegenService;
18 import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; 18 import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
19 import cn.iocoder.yudao.framework.common.util.servlet.ServletUtils; 19 import cn.iocoder.yudao.framework.common.util.servlet.ServletUtils;
@@ -58,7 +58,7 @@ public class CodegenController { @@ -58,7 +58,7 @@ public class CodegenController {
58 @RequestParam(value = "tableName", required = false) String tableName, 58 @RequestParam(value = "tableName", required = false) String tableName,
59 @RequestParam(value = "tableComment", required = false) String tableComment) { 59 @RequestParam(value = "tableComment", required = false) String tableComment) {
60 // 获得数据库自带的表定义列表 60 // 获得数据库自带的表定义列表
61 - List<SchemaTableDO> schemaTables = codegenService.getSchemaTableList(tableName, tableComment); 61 + List<DatabaseTableDO> schemaTables = codegenService.getSchemaTableList(tableName, tableComment);
62 // 移除在 Codegen 中,已经存在的 62 // 移除在 Codegen 中,已经存在的
63 Set<String> existsTables = CollectionUtils.convertSet(codegenService.getCodeGenTableList(), CodegenTableDO::getTableName); 63 Set<String> existsTables = CollectionUtils.convertSet(codegenService.getCodeGenTableList(), CodegenTableDO::getTableName);
64 schemaTables.removeIf(table -> existsTables.contains(table.getTableName())); 64 schemaTables.removeIf(table -> existsTables.contains(table.getTableName()));
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 @@ -9,8 +9,8 @@ import cn.iocoder.yudao.module.infra.controller.admin.codegen.vo.table.CodegenTa
9 import cn.iocoder.yudao.module.infra.controller.admin.codegen.vo.table.SchemaTableRespVO; 9 import cn.iocoder.yudao.module.infra.controller.admin.codegen.vo.table.SchemaTableRespVO;
10 import cn.iocoder.yudao.module.infra.dal.dataobject.codegen.CodegenColumnDO; 10 import cn.iocoder.yudao.module.infra.dal.dataobject.codegen.CodegenColumnDO;
11 import cn.iocoder.yudao.module.infra.dal.dataobject.codegen.CodegenTableDO; 11 import cn.iocoder.yudao.module.infra.dal.dataobject.codegen.CodegenTableDO;
12 -import cn.iocoder.yudao.module.infra.dal.dataobject.codegen.SchemaColumnDO;  
13 -import cn.iocoder.yudao.module.infra.dal.dataobject.codegen.SchemaTableDO; 12 +import cn.iocoder.yudao.module.infra.dal.dataobject.db.DatabaseColumnDO;
  13 +import cn.iocoder.yudao.module.infra.dal.dataobject.db.DatabaseTableDO;
14 import org.mapstruct.Mapper; 14 import org.mapstruct.Mapper;
15 import org.mapstruct.factory.Mappers; 15 import org.mapstruct.factory.Mappers;
16 16
@@ -25,11 +25,11 @@ public interface CodegenConvert { @@ -25,11 +25,11 @@ public interface CodegenConvert {
25 25
26 // ========== InformationSchemaTableDO 和 InformationSchemaColumnDO 相关 ========== 26 // ========== InformationSchemaTableDO 和 InformationSchemaColumnDO 相关 ==========
27 27
28 - CodegenTableDO convert(SchemaTableDO bean); 28 + CodegenTableDO convert(DatabaseTableDO bean);
29 29
30 - List<CodegenColumnDO> convertList(List<SchemaColumnDO> list); 30 + List<CodegenColumnDO> convertList(List<DatabaseColumnDO> list);
31 31
32 - CodegenTableRespVO convert(SchemaColumnDO bean); 32 + CodegenTableRespVO convert(DatabaseColumnDO bean);
33 33
34 // ========== CodegenTableDO 相关 ========== 34 // ========== CodegenTableDO 相关 ==========
35 35
@@ -47,7 +47,7 @@ public interface CodegenConvert { @@ -47,7 +47,7 @@ public interface CodegenConvert {
47 47
48 List<CodegenColumnDO> convertList03(List<CodegenUpdateReqVO.Column> columns); 48 List<CodegenColumnDO> convertList03(List<CodegenUpdateReqVO.Column> columns);
49 49
50 - List<SchemaTableRespVO> convertList04(List<SchemaTableDO> list); 50 + List<SchemaTableRespVO> convertList04(List<DatabaseTableDO> list);
51 51
52 // ========== 其它 ========== 52 // ========== 其它 ==========
53 53
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 { @@ -74,7 +74,6 @@ public class CodegenColumnDO extends BaseDO {
74 /** 74 /**
75 * Java 属性名 75 * Java 属性名
76 */ 76 */
77 -// @NotBlank(message = "Java属性不能为空")  
78 private String javaField; 77 private String javaField;
79 /** 78 /**
80 * 字典类型 79 * 字典类型
yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/dataobject/db/DataSourceConfigDO.java
@@ -14,6 +14,11 @@ import lombok.Data; @@ -14,6 +14,11 @@ import lombok.Data;
14 public class DataSourceConfigDO extends BaseDO { 14 public class DataSourceConfigDO extends BaseDO {
15 15
16 /** 16 /**
  17 + * 主键编号 - Master 数据源
  18 + */
  19 + public static final Long ID_MASTER = 0L;
  20 +
  21 + /**
17 * 主键编号 22 * 主键编号
18 */ 23 */
19 private Long id; 24 private Long id;
yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/dataobject/codegen/SchemaColumnDO.java renamed to yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/dataobject/db/DatabaseColumnDO.java
1 -package cn.iocoder.yudao.module.infra.dal.dataobject.codegen; 1 +package cn.iocoder.yudao.module.infra.dal.dataobject.db;
2 2
3 import com.baomidou.mybatisplus.annotation.TableField; 3 import com.baomidou.mybatisplus.annotation.TableField;
4 import com.baomidou.mybatisplus.annotation.TableName; 4 import com.baomidou.mybatisplus.annotation.TableName;
@@ -10,10 +10,9 @@ import lombok.Data; @@ -10,10 +10,9 @@ import lombok.Data;
10 * 10 *
11 * @author 芋道源码 11 * @author 芋道源码
12 */ 12 */
13 -@TableName(value = "information_schema.columns", autoResultMap = true)  
14 @Data 13 @Data
15 @Builder 14 @Builder
16 -public class SchemaColumnDO { 15 +public class DatabaseColumnDO {
17 16
18 /** 17 /**
19 * 表名称 18 * 表名称
@@ -34,17 +33,14 @@ public class SchemaColumnDO { @@ -34,17 +33,14 @@ public class SchemaColumnDO {
34 /** 33 /**
35 * 是否允许为空 34 * 是否允许为空
36 */ 35 */
37 - @TableField("case when is_nullable = 'yes' then '1' else '0' end")  
38 private Boolean nullable; 36 private Boolean nullable;
39 /** 37 /**
40 * 是否主键 38 * 是否主键
41 */ 39 */
42 - @TableField("case when column_key = 'PRI' then '1' else '0' end")  
43 private Boolean primaryKey; 40 private Boolean primaryKey;
44 /** 41 /**
45 * 是否自增 42 * 是否自增
46 */ 43 */
47 - @TableField("case when extra = 'auto_increment' then '1' else '0' end")  
48 private Boolean autoIncrement; 44 private Boolean autoIncrement;
49 /** 45 /**
50 * 排序字段 46 * 排序字段
yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/dataobject/codegen/SchemaTableDO.java renamed to yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/dataobject/db/DatabaseTableDO.java
1 -package cn.iocoder.yudao.module.infra.dal.dataobject.codegen; 1 +package cn.iocoder.yudao.module.infra.dal.dataobject.db;
2 2
3 -import com.baomidou.mybatisplus.annotation.TableName;  
4 import lombok.Builder; 3 import lombok.Builder;
5 import lombok.Data; 4 import lombok.Data;
6 5
@@ -11,16 +10,11 @@ import java.util.Date; @@ -11,16 +10,11 @@ import java.util.Date;
11 * 10 *
12 * @author 芋道源码 11 * @author 芋道源码
13 */ 12 */
14 -@TableName(value = "information_schema.tables", autoResultMap = true)  
15 @Data 13 @Data
16 @Builder 14 @Builder
17 -public class SchemaTableDO { 15 +public class DatabaseTableDO {
18 16
19 /** 17 /**
20 - * 数据库  
21 - */  
22 - private String tableSchema;  
23 - /**  
24 * 表名称 18 * 表名称
25 */ 19 */
26 private String tableName; 20 private String tableName;
yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/mysql/codegen/SchemaColumnMapper.java deleted
1 -package cn.iocoder.yudao.module.infra.dal.mysql.codegen;  
2 -  
3 -import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;  
4 -import cn.iocoder.yudao.module.infra.dal.dataobject.codegen.SchemaColumnDO;  
5 -import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;  
6 -import org.apache.ibatis.annotations.Mapper;  
7 -  
8 -import java.util.List;  
9 -  
10 -@Mapper  
11 -public interface SchemaColumnMapper extends BaseMapperX<SchemaColumnDO> {  
12 -  
13 - default List<SchemaColumnDO> selectListByTableName(String tableSchema, String tableName) {  
14 - return selectList(new QueryWrapper<SchemaColumnDO>().eq("table_name", tableName)  
15 - .eq("table_schema", tableSchema)  
16 - .orderByAsc("ordinal_position"));  
17 - }  
18 -  
19 -}  
yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/mysql/codegen/SchemaTableMapper.java deleted
1 -package cn.iocoder.yudao.module.infra.dal.mysql.codegen;  
2 -  
3 -import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;  
4 -import cn.iocoder.yudao.framework.mybatis.core.query.QueryWrapperX;  
5 -import cn.iocoder.yudao.module.infra.dal.dataobject.codegen.SchemaTableDO;  
6 -import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;  
7 -import org.apache.ibatis.annotations.Mapper;  
8 -  
9 -import java.util.Collection;  
10 -import java.util.List;  
11 -  
12 -@Mapper  
13 -public interface SchemaTableMapper extends BaseMapperX<SchemaTableDO> {  
14 -  
15 - default List<SchemaTableDO> selectList(Collection<String> tableSchemas, String tableName, String tableComment) {  
16 - return selectList(new QueryWrapperX<SchemaTableDO>().in("table_schema", tableSchemas)  
17 - .likeIfPresent("table_name", tableName)  
18 - .likeIfPresent("table_comment", tableComment));  
19 - }  
20 -  
21 - default SchemaTableDO selectByTableSchemaAndTableName(String tableSchema, String tableName) {  
22 - return selectOne(new QueryWrapper<SchemaTableDO>().eq("table_schema",tableSchema)  
23 - .eq("table_name", tableName));  
24 - }  
25 -  
26 -}  
yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/mysql/db/DatabaseTableDAO.java 0 → 100644
  1 +package cn.iocoder.yudao.module.infra.dal.mysql.db;
  2 +
  3 +import cn.hutool.core.collection.CollUtil;
  4 +import cn.iocoder.yudao.module.infra.dal.dataobject.db.DatabaseColumnDO;
  5 +import cn.iocoder.yudao.module.infra.dal.dataobject.db.DatabaseTableDO;
  6 +import com.baomidou.mybatisplus.annotation.DbType;
  7 +
  8 +import java.sql.Connection;
  9 +import java.util.List;
  10 +
  11 +/**
  12 + * 数据库 Table DAO 接口
  13 + *
  14 + * @author 芋道源码
  15 + */
  16 +public interface DatabaseTableDAO {
  17 +
  18 + /**
  19 + * 获得表列表,基于表名称 + 表描述进行模糊匹配
  20 + *
  21 + * @param connection 数据库连接
  22 + * @param tableNameLike 表名称,模糊匹配
  23 + * @param tableCommentLike 表描述,模糊匹配
  24 + * @return 表列表
  25 + */
  26 + List<DatabaseTableDO> selectTableList(Connection connection, String tableNameLike, String tableCommentLike);
  27 +
  28 + /**
  29 + * 获得指定表名
  30 + *
  31 + * @param connection 数据库连接
  32 + * @param tableName 表名称
  33 + * @return 表
  34 + */
  35 + default DatabaseTableDO selectTable(Connection connection, String tableName) {
  36 + // 考虑到对性能没有要求,直接查询列表,然后内存过滤到记录
  37 + List<DatabaseTableDO> tables = selectTableList(connection, tableName, null);
  38 + return CollUtil.findOne(tables, table -> table.getTableName().equalsIgnoreCase(tableName));
  39 + }
  40 +
  41 + /**
  42 + * 获得指定表的字段列表
  43 + *
  44 + * @param connection 数据库连接
  45 + * @param tableName 表名称
  46 + * @return 字段列表
  47 + */
  48 + List<DatabaseColumnDO> selectColumnList(Connection connection, String tableName);
  49 +
  50 + /**
  51 + * 获得数据库的类型
  52 + *
  53 + * @return 数据库的类型
  54 + */
  55 + DbType getType();
  56 +
  57 +}
yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/mysql/db/DatabaseTableMySQLDAOImpl.java 0 → 100644
  1 +package cn.iocoder.yudao.module.infra.dal.mysql.db;
  2 +
  3 +import cn.hutool.core.util.StrUtil;
  4 +import cn.iocoder.yudao.framework.mybatis.core.util.JdbcUtils;
  5 +import cn.iocoder.yudao.module.infra.dal.dataobject.db.DatabaseColumnDO;
  6 +import cn.iocoder.yudao.module.infra.dal.dataobject.db.DatabaseTableDO;
  7 +import com.baomidou.mybatisplus.annotation.DbType;
  8 +import org.springframework.stereotype.Repository;
  9 +
  10 +import java.sql.Connection;
  11 +import java.util.List;
  12 +
  13 +/**
  14 + * {@link DatabaseTableDAO} 的 MySQL 实现类
  15 + *
  16 + * @author 芋道源码
  17 + */
  18 +@Repository
  19 +public class DatabaseTableMySQLDAOImpl implements DatabaseTableDAO {
  20 +
  21 + @Override
  22 + public List<DatabaseTableDO> selectTableList(Connection connection, String tableNameLike, String tableCommentLike) {
  23 + // 拼接 SQL
  24 + String sql = "SELECT table_name, table_comment, create_time" +
  25 + " FROM information_schema.TABLES" +
  26 + " WHERE table_schema = (SELECT DATABASE())";
  27 + if (StrUtil.isNotEmpty(tableNameLike)) {
  28 + sql += StrUtil.format(" AND table_name LIKE '%{}%'", tableNameLike);
  29 + }
  30 + if (StrUtil.isNotEmpty(tableCommentLike)) {
  31 + sql += StrUtil.format(" AND table_comment LIKE '%{}%'", tableCommentLike);
  32 + }
  33 + // 执行并返回结果
  34 + return JdbcUtils.query(connection, sql, (rs, rowNum) -> DatabaseTableDO.builder()
  35 + .tableName(rs.getString("table_name"))
  36 + .tableComment(rs.getString("table_comment"))
  37 + .createTime(rs.getDate("create_time"))
  38 + .build());
  39 + }
  40 +
  41 + @Override
  42 + public List<DatabaseColumnDO> selectColumnList(Connection connection, String tableName) {
  43 + // 拼接 SQL
  44 + String sql = "SELECT table_name, column_name, column_type, column_comment, " +
  45 + " (CASE WHEN is_nullable = 'yes' THEN '1' ELSE '0' END) AS nullable," +
  46 + " (CASE WHEN column_key = 'PRI' THEN '1' ELSE '0' END) AS primary_key," +
  47 + " (CASE WHEN extra = 'auto_increment' THEN '1' ELSE '0' END) AS auto_increment," +
  48 + " ordinal_position" +
  49 + " FROM information_schema.COLUMNS" +
  50 + " WHERE table_schema = (SELECT DATABASE())" +
  51 + String.format(" AND table_name = '%s'", tableName);
  52 + // 执行并返回结果
  53 + return JdbcUtils.query(connection, sql, (rs, rowNum) -> DatabaseColumnDO.builder()
  54 + .tableName(rs.getString("table_name"))
  55 + .columnName(rs.getString("column_name"))
  56 + .columnType(rs.getString("column_type"))
  57 + .columnComment(rs.getString("column_comment"))
  58 + .nullable(rs.getBoolean("nullable"))
  59 + .primaryKey(rs.getBoolean("primary_key"))
  60 + .autoIncrement(rs.getBoolean("auto_increment"))
  61 + .ordinalPosition(rs.getInt("ordinal_position"))
  62 + .build());
  63 + }
  64 +
  65 + @Override
  66 + public DbType getType() {
  67 + return DbType.MYSQL;
  68 + }
  69 +
  70 +}
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 @@ -5,7 +5,7 @@ import cn.iocoder.yudao.module.infra.controller.admin.codegen.vo.CodegenUpdateRe
5 import cn.iocoder.yudao.module.infra.controller.admin.codegen.vo.table.CodegenTablePageReqVO; 5 import cn.iocoder.yudao.module.infra.controller.admin.codegen.vo.table.CodegenTablePageReqVO;
6 import cn.iocoder.yudao.module.infra.dal.dataobject.codegen.CodegenColumnDO; 6 import cn.iocoder.yudao.module.infra.dal.dataobject.codegen.CodegenColumnDO;
7 import cn.iocoder.yudao.module.infra.dal.dataobject.codegen.CodegenTableDO; 7 import cn.iocoder.yudao.module.infra.dal.dataobject.codegen.CodegenTableDO;
8 -import cn.iocoder.yudao.module.infra.dal.dataobject.codegen.SchemaTableDO; 8 +import cn.iocoder.yudao.module.infra.dal.dataobject.db.DatabaseTableDO;
9 9
10 import java.util.List; 10 import java.util.List;
11 import java.util.Map; 11 import java.util.Map;
@@ -119,6 +119,6 @@ public interface CodegenService { @@ -119,6 +119,6 @@ public interface CodegenService {
119 * @param tableComment 表描述 119 * @param tableComment 表描述
120 * @return 表定义列表 120 * @return 表定义列表
121 */ 121 */
122 - List<SchemaTableDO> getSchemaTableList(String tableName, String tableComment); 122 + List<DatabaseTableDO> getSchemaTableList(String tableName, String tableComment);
123 123
124 } 124 }
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 @@ -8,17 +8,16 @@ import cn.iocoder.yudao.module.infra.controller.admin.codegen.vo.table.CodegenTa
8 import cn.iocoder.yudao.module.infra.convert.codegen.CodegenConvert; 8 import cn.iocoder.yudao.module.infra.convert.codegen.CodegenConvert;
9 import cn.iocoder.yudao.module.infra.dal.dataobject.codegen.CodegenColumnDO; 9 import cn.iocoder.yudao.module.infra.dal.dataobject.codegen.CodegenColumnDO;
10 import cn.iocoder.yudao.module.infra.dal.dataobject.codegen.CodegenTableDO; 10 import cn.iocoder.yudao.module.infra.dal.dataobject.codegen.CodegenTableDO;
11 -import cn.iocoder.yudao.module.infra.dal.dataobject.codegen.SchemaColumnDO;  
12 -import cn.iocoder.yudao.module.infra.dal.dataobject.codegen.SchemaTableDO; 11 +import cn.iocoder.yudao.module.infra.dal.dataobject.db.DatabaseColumnDO;
  12 +import cn.iocoder.yudao.module.infra.dal.dataobject.db.DatabaseTableDO;
13 import cn.iocoder.yudao.module.infra.dal.mysql.codegen.CodegenColumnMapper; 13 import cn.iocoder.yudao.module.infra.dal.mysql.codegen.CodegenColumnMapper;
14 import cn.iocoder.yudao.module.infra.dal.mysql.codegen.CodegenTableMapper; 14 import cn.iocoder.yudao.module.infra.dal.mysql.codegen.CodegenTableMapper;
15 -import cn.iocoder.yudao.module.infra.dal.mysql.codegen.SchemaColumnMapper;  
16 -import cn.iocoder.yudao.module.infra.dal.mysql.codegen.SchemaTableMapper;  
17 import cn.iocoder.yudao.module.infra.enums.codegen.CodegenImportTypeEnum; 15 import cn.iocoder.yudao.module.infra.enums.codegen.CodegenImportTypeEnum;
18 import cn.iocoder.yudao.module.infra.framework.codegen.config.CodegenProperties; 16 import cn.iocoder.yudao.module.infra.framework.codegen.config.CodegenProperties;
19 import cn.iocoder.yudao.module.infra.service.codegen.inner.CodegenBuilder; 17 import cn.iocoder.yudao.module.infra.service.codegen.inner.CodegenBuilder;
20 import cn.iocoder.yudao.module.infra.service.codegen.inner.CodegenEngine; 18 import cn.iocoder.yudao.module.infra.service.codegen.inner.CodegenEngine;
21 import cn.iocoder.yudao.module.infra.service.codegen.inner.CodegenSQLParser; 19 import cn.iocoder.yudao.module.infra.service.codegen.inner.CodegenSQLParser;
  20 +import cn.iocoder.yudao.module.infra.service.db.DatabaseTableService;
22 import cn.iocoder.yudao.module.system.api.user.AdminUserApi; 21 import cn.iocoder.yudao.module.system.api.user.AdminUserApi;
23 import org.apache.commons.collections4.KeyValue; 22 import org.apache.commons.collections4.KeyValue;
24 import org.springframework.stereotype.Service; 23 import org.springframework.stereotype.Service;
@@ -43,9 +42,8 @@ import static cn.iocoder.yudao.module.infra.enums.ErrorCodeConstants.*; @@ -43,9 +42,8 @@ import static cn.iocoder.yudao.module.infra.enums.ErrorCodeConstants.*;
43 public class CodegenServiceImpl implements CodegenService { 42 public class CodegenServiceImpl implements CodegenService {
44 43
45 @Resource 44 @Resource
46 - private SchemaTableMapper schemaTableMapper;  
47 - @Resource  
48 - private SchemaColumnMapper schemaColumnMapper; 45 + private DatabaseTableService databaseTableService;
  46 +
49 @Resource 47 @Resource
50 private CodegenTableMapper codegenTableMapper; 48 private CodegenTableMapper codegenTableMapper;
51 @Resource 49 @Resource
@@ -63,7 +61,7 @@ public class CodegenServiceImpl implements CodegenService { @@ -63,7 +61,7 @@ public class CodegenServiceImpl implements CodegenService {
63 private CodegenProperties codegenProperties; 61 private CodegenProperties codegenProperties;
64 62
65 private Long createCodegen0(Long userId, CodegenImportTypeEnum importType, 63 private Long createCodegen0(Long userId, CodegenImportTypeEnum importType,
66 - SchemaTableDO schemaTable, List<SchemaColumnDO> schemaColumns) { 64 + DatabaseTableDO schemaTable, List<DatabaseColumnDO> schemaColumns) {
67 // 校验导入的表和字段非空 65 // 校验导入的表和字段非空
68 if (schemaTable == null) { 66 if (schemaTable == null) {
69 throw exception(CODEGEN_IMPORT_TABLE_NULL); 67 throw exception(CODEGEN_IMPORT_TABLE_NULL);
@@ -90,10 +88,10 @@ public class CodegenServiceImpl implements CodegenService { @@ -90,10 +88,10 @@ public class CodegenServiceImpl implements CodegenService {
90 @Override 88 @Override
91 public Long createCodegenListFromSQL(Long userId, String sql) { 89 public Long createCodegenListFromSQL(Long userId, String sql) {
92 // 从 SQL 中,获得数据库表结构 90 // 从 SQL 中,获得数据库表结构
93 - SchemaTableDO schemaTable;  
94 - List<SchemaColumnDO> schemaColumns; 91 + DatabaseTableDO schemaTable;
  92 + List<DatabaseColumnDO> schemaColumns;
95 try { 93 try {
96 - KeyValue<SchemaTableDO, List<SchemaColumnDO>> result = CodegenSQLParser.parse(sql); 94 + KeyValue<DatabaseTableDO, List<DatabaseColumnDO>> result = CodegenSQLParser.parse(sql);
97 schemaTable = result.getKey(); 95 schemaTable = result.getKey();
98 schemaColumns = result.getValue(); 96 schemaColumns = result.getValue();
99 } catch (Exception ex) { 97 } catch (Exception ex) {
@@ -108,8 +106,8 @@ public class CodegenServiceImpl implements CodegenService { @@ -108,8 +106,8 @@ public class CodegenServiceImpl implements CodegenService {
108 // 获取当前schema 106 // 获取当前schema
109 String tableSchema = codegenProperties.getDbSchemas().iterator().next(); 107 String tableSchema = codegenProperties.getDbSchemas().iterator().next();
110 // 从数据库中,获得数据库表结构 108 // 从数据库中,获得数据库表结构
111 - SchemaTableDO schemaTable = schemaTableMapper.selectByTableSchemaAndTableName(tableSchema, tableName);  
112 - List<SchemaColumnDO> schemaColumns = schemaColumnMapper.selectListByTableName(tableSchema, tableName); 109 + DatabaseTableDO schemaTable = databaseTableService.getTable(0L, tableName);
  110 + List<DatabaseColumnDO> schemaColumns = databaseTableService.getColumnList(0L, tableName);
113 // 导入 111 // 导入
114 return this.createCodegen0(userId, CodegenImportTypeEnum.DB, schemaTable, schemaColumns); 112 return this.createCodegen0(userId, CodegenImportTypeEnum.DB, schemaTable, schemaColumns);
115 } 113 }
@@ -147,9 +145,8 @@ public class CodegenServiceImpl implements CodegenService { @@ -147,9 +145,8 @@ public class CodegenServiceImpl implements CodegenService {
147 if (table == null) { 145 if (table == null) {
148 throw exception(CODEGEN_TABLE_NOT_EXISTS); 146 throw exception(CODEGEN_TABLE_NOT_EXISTS);
149 } 147 }
150 - String tableSchema = codegenProperties.getDbSchemas().iterator().next();  
151 // 从数据库中,获得数据库表结构 148 // 从数据库中,获得数据库表结构
152 - List<SchemaColumnDO> schemaColumns = schemaColumnMapper.selectListByTableName(tableSchema, table.getTableName()); 149 + List<DatabaseColumnDO> schemaColumns = databaseTableService.getColumnList(0L, table.getTableName());
153 150
154 // 执行同步 151 // 执行同步
155 this.syncCodegen0(tableId, schemaColumns); 152 this.syncCodegen0(tableId, schemaColumns);
@@ -164,9 +161,9 @@ public class CodegenServiceImpl implements CodegenService { @@ -164,9 +161,9 @@ public class CodegenServiceImpl implements CodegenService {
164 throw exception(CODEGEN_TABLE_NOT_EXISTS); 161 throw exception(CODEGEN_TABLE_NOT_EXISTS);
165 } 162 }
166 // 从 SQL 中,获得数据库表结构 163 // 从 SQL 中,获得数据库表结构
167 - List<SchemaColumnDO> schemaColumns; 164 + List<DatabaseColumnDO> schemaColumns;
168 try { 165 try {
169 - KeyValue<SchemaTableDO, List<SchemaColumnDO>> result = CodegenSQLParser.parse(sql); 166 + KeyValue<DatabaseTableDO, List<DatabaseColumnDO>> result = CodegenSQLParser.parse(sql);
170 schemaColumns = result.getValue(); 167 schemaColumns = result.getValue();
171 } catch (Exception ex) { 168 } catch (Exception ex) {
172 throw exception(CODEGEN_PARSE_SQL_ERROR); 169 throw exception(CODEGEN_PARSE_SQL_ERROR);
@@ -176,12 +173,12 @@ public class CodegenServiceImpl implements CodegenService { @@ -176,12 +173,12 @@ public class CodegenServiceImpl implements CodegenService {
176 this.syncCodegen0(tableId, schemaColumns); 173 this.syncCodegen0(tableId, schemaColumns);
177 } 174 }
178 175
179 - private void syncCodegen0(Long tableId, List<SchemaColumnDO> schemaColumns) { 176 + private void syncCodegen0(Long tableId, List<DatabaseColumnDO> schemaColumns) {
180 // 校验导入的字段不为空 177 // 校验导入的字段不为空
181 if (CollUtil.isEmpty(schemaColumns)) { 178 if (CollUtil.isEmpty(schemaColumns)) {
182 throw exception(CODEGEN_SYNC_COLUMNS_NULL); 179 throw exception(CODEGEN_SYNC_COLUMNS_NULL);
183 } 180 }
184 - Set<String> schemaColumnNames = CollectionUtils.convertSet(schemaColumns, SchemaColumnDO::getColumnName); 181 + Set<String> schemaColumnNames = CollectionUtils.convertSet(schemaColumns, DatabaseColumnDO::getColumnName);
185 182
186 // 构建 CodegenColumnDO 数组,只同步新增的字段 183 // 构建 CodegenColumnDO 数组,只同步新增的字段
187 List<CodegenColumnDO> codegenColumns = codegenColumnMapper.selectListByTableId(tableId); 184 List<CodegenColumnDO> codegenColumns = codegenColumnMapper.selectListByTableId(tableId);
@@ -255,8 +252,8 @@ public class CodegenServiceImpl implements CodegenService { @@ -255,8 +252,8 @@ public class CodegenServiceImpl implements CodegenService {
255 } 252 }
256 253
257 @Override 254 @Override
258 - public List<SchemaTableDO> getSchemaTableList(String tableName, String tableComment) {  
259 - List<SchemaTableDO> tables = schemaTableMapper.selectList(codegenProperties.getDbSchemas(), tableName, tableComment); 255 + public List<DatabaseTableDO> getSchemaTableList(String tableName, String tableComment) {
  256 + List<DatabaseTableDO> tables = databaseTableService.getTableList(0L, tableName, tableComment);
260 // TODO 强制移除 Quartz 的表,未来做成可配置 257 // TODO 强制移除 Quartz 的表,未来做成可配置
261 tables.removeIf(table -> table.getTableName().startsWith("QRTZ_")); 258 tables.removeIf(table -> table.getTableName().startsWith("QRTZ_"));
262 tables.removeIf(table -> table.getTableName().startsWith("ACT_")); 259 tables.removeIf(table -> table.getTableName().startsWith("ACT_"));
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; @@ -7,8 +7,8 @@ import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
7 import cn.iocoder.yudao.module.infra.convert.codegen.CodegenConvert; 7 import cn.iocoder.yudao.module.infra.convert.codegen.CodegenConvert;
8 import cn.iocoder.yudao.module.infra.dal.dataobject.codegen.CodegenColumnDO; 8 import cn.iocoder.yudao.module.infra.dal.dataobject.codegen.CodegenColumnDO;
9 import cn.iocoder.yudao.module.infra.dal.dataobject.codegen.CodegenTableDO; 9 import cn.iocoder.yudao.module.infra.dal.dataobject.codegen.CodegenTableDO;
10 -import cn.iocoder.yudao.module.infra.dal.dataobject.codegen.SchemaColumnDO;  
11 -import cn.iocoder.yudao.module.infra.dal.dataobject.codegen.SchemaTableDO; 10 +import cn.iocoder.yudao.module.infra.dal.dataobject.db.DatabaseColumnDO;
  11 +import cn.iocoder.yudao.module.infra.dal.dataobject.db.DatabaseTableDO;
12 import cn.iocoder.yudao.module.infra.enums.codegen.CodegenColumnHtmlTypeEnum; 12 import cn.iocoder.yudao.module.infra.enums.codegen.CodegenColumnHtmlTypeEnum;
13 import cn.iocoder.yudao.module.infra.enums.codegen.CodegenColumnListConditionEnum; 13 import cn.iocoder.yudao.module.infra.enums.codegen.CodegenColumnListConditionEnum;
14 import cn.iocoder.yudao.module.infra.enums.codegen.CodegenTemplateTypeEnum; 14 import cn.iocoder.yudao.module.infra.enums.codegen.CodegenTemplateTypeEnum;
@@ -22,8 +22,8 @@ import static cn.hutool.core.text.CharSequenceUtil.*; @@ -22,8 +22,8 @@ import static cn.hutool.core.text.CharSequenceUtil.*;
22 22
23 /** 23 /**
24 * 代码生成器的 Builder,负责: 24 * 代码生成器的 Builder,负责:
25 - * 1. 将数据库的表 {@link SchemaTableDO} 定义,构建成 {@link CodegenTableDO}  
26 - * 2. 将数据库的列 {@link SchemaColumnDO} 构定义,建成 {@link CodegenColumnDO} 25 + * 1. 将数据库的表 {@link DatabaseTableDO} 定义,构建成 {@link CodegenTableDO}
  26 + * 2. 将数据库的列 {@link DatabaseColumnDO} 构定义,建成 {@link CodegenColumnDO}
27 */ 27 */
28 @Component 28 @Component
29 public class CodegenBuilder { 29 public class CodegenBuilder {
@@ -109,7 +109,7 @@ public class CodegenBuilder { @@ -109,7 +109,7 @@ public class CodegenBuilder {
109 LIST_OPERATION_RESULT_EXCLUDE_COLUMN.remove("createTime"); // 创建时间,还是需要返回的 109 LIST_OPERATION_RESULT_EXCLUDE_COLUMN.remove("createTime"); // 创建时间,还是需要返回的
110 } 110 }
111 111
112 - public CodegenTableDO buildTable(SchemaTableDO schemaTable) { 112 + public CodegenTableDO buildTable(DatabaseTableDO schemaTable) {
113 CodegenTableDO table = CodegenConvert.INSTANCE.convert(schemaTable); 113 CodegenTableDO table = CodegenConvert.INSTANCE.convert(schemaTable);
114 initTableDefault(table); 114 initTableDefault(table);
115 return table; 115 return table;
@@ -133,7 +133,7 @@ public class CodegenBuilder { @@ -133,7 +133,7 @@ public class CodegenBuilder {
133 table.setTemplateType(CodegenTemplateTypeEnum.CRUD.getType()); 133 table.setTemplateType(CodegenTemplateTypeEnum.CRUD.getType());
134 } 134 }
135 135
136 - public List<CodegenColumnDO> buildColumns(Long tableId, List<SchemaColumnDO> schemaColumns) { 136 + public List<CodegenColumnDO> buildColumns(Long tableId, List<DatabaseColumnDO> schemaColumns) {
137 List<CodegenColumnDO> columns = CodegenConvert.INSTANCE.convertList(schemaColumns); 137 List<CodegenColumnDO> columns = CodegenConvert.INSTANCE.convertList(schemaColumns);
138 for (CodegenColumnDO column : columns) { 138 for (CodegenColumnDO column : columns) {
139 column.setTableId(tableId); 139 column.setTableId(tableId);
yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/codegen/inner/CodegenSQLParser.java
1 package cn.iocoder.yudao.module.infra.service.codegen.inner; 1 package cn.iocoder.yudao.module.infra.service.codegen.inner;
2 2
3 import cn.hutool.core.collection.CollUtil; 3 import cn.hutool.core.collection.CollUtil;
4 -import cn.iocoder.yudao.module.infra.dal.dataobject.codegen.SchemaColumnDO;  
5 -import cn.iocoder.yudao.module.infra.dal.dataobject.codegen.SchemaTableDO; 4 +import cn.iocoder.yudao.module.infra.dal.dataobject.db.DatabaseColumnDO;
  5 +import cn.iocoder.yudao.module.infra.dal.dataobject.db.DatabaseTableDO;
6 import com.alibaba.druid.DbType; 6 import com.alibaba.druid.DbType;
7 import com.alibaba.druid.sql.ast.expr.SQLCharExpr; 7 import com.alibaba.druid.sql.ast.expr.SQLCharExpr;
8 import com.alibaba.druid.sql.ast.statement.SQLColumnDefinition; 8 import com.alibaba.druid.sql.ast.statement.SQLColumnDefinition;
@@ -21,7 +21,7 @@ import java.util.Objects; @@ -21,7 +21,7 @@ import java.util.Objects;
21 import static com.alibaba.druid.sql.SQLUtils.normalize; 21 import static com.alibaba.druid.sql.SQLUtils.normalize;
22 22
23 /** 23 /**
24 - * SQL 解析器,将创建表的 SQL,解析成 {@link SchemaTableDO} 和 {@link SchemaColumnDO} 对象, 24 + * SQL 解析器,将创建表的 SQL,解析成 {@link DatabaseTableDO} 和 {@link DatabaseColumnDO} 对象,
25 * 后续可以基于它们,生成代码~ 25 * 后续可以基于它们,生成代码~
26 * 26 *
27 * @author 芋道源码 27 * @author 芋道源码
@@ -29,18 +29,18 @@ import static com.alibaba.druid.sql.SQLUtils.normalize; @@ -29,18 +29,18 @@ import static com.alibaba.druid.sql.SQLUtils.normalize;
29 public class CodegenSQLParser { 29 public class CodegenSQLParser {
30 30
31 /** 31 /**
32 - * 解析建表 SQL 语句,返回 {@link SchemaTableDO} 和 {@link SchemaColumnDO} 对象 32 + * 解析建表 SQL 语句,返回 {@link DatabaseTableDO} 和 {@link DatabaseColumnDO} 对象
33 * 33 *
34 * @param sql 建表 SQL 语句 34 * @param sql 建表 SQL 语句
35 * @return 解析结果 35 * @return 解析结果
36 */ 36 */
37 - public static KeyValue<SchemaTableDO, List<SchemaColumnDO>> parse(String sql) { 37 + public static KeyValue<DatabaseTableDO, List<DatabaseColumnDO>> parse(String sql) {
38 // 解析 SQL 成 Statement 38 // 解析 SQL 成 Statement
39 SQLCreateTableStatement statement = parseCreateSQL(sql); 39 SQLCreateTableStatement statement = parseCreateSQL(sql);
40 // 解析 Table 表 40 // 解析 Table 表
41 - SchemaTableDO table = parseTable(statement); 41 + DatabaseTableDO table = parseTable(statement);
42 // 解析 Column 字段 42 // 解析 Column 字段
43 - List<SchemaColumnDO> columns = parseColumns(statement); 43 + List<DatabaseColumnDO> columns = parseColumns(statement);
44 columns.forEach(column -> column.setTableName(table.getTableName())); 44 columns.forEach(column -> column.setTableName(table.getTableName()));
45 // 返回 45 // 返回
46 return new DefaultKeyValue<>(table, columns); 46 return new DefaultKeyValue<>(table, columns);
@@ -61,8 +61,8 @@ public class CodegenSQLParser { @@ -61,8 +61,8 @@ public class CodegenSQLParser {
61 return (MySqlCreateTableStatement) repository.findTable(tableName).getStatement(); 61 return (MySqlCreateTableStatement) repository.findTable(tableName).getStatement();
62 } 62 }
63 63
64 - private static SchemaTableDO parseTable(SQLCreateTableStatement statement) {  
65 - return SchemaTableDO.builder() 64 + private static DatabaseTableDO parseTable(SQLCreateTableStatement statement) {
  65 + return DatabaseTableDO.builder()
66 .tableName(statement.getTableSource().getTableName(true)) 66 .tableName(statement.getTableSource().getTableName(true))
67 .tableComment(getCommentText(statement)) 67 .tableComment(getCommentText(statement))
68 .build(); 68 .build();
@@ -75,13 +75,13 @@ public class CodegenSQLParser { @@ -75,13 +75,13 @@ public class CodegenSQLParser {
75 return ((SQLCharExpr) statement.getComment()).getText(); 75 return ((SQLCharExpr) statement.getComment()).getText();
76 } 76 }
77 77
78 - private static List<SchemaColumnDO> parseColumns(SQLCreateTableStatement statement) {  
79 - List<SchemaColumnDO> columns = new ArrayList<>(); 78 + private static List<DatabaseColumnDO> parseColumns(SQLCreateTableStatement statement) {
  79 + List<DatabaseColumnDO> columns = new ArrayList<>();
80 statement.getTableElementList().forEach(element -> parseColumn(columns, element)); 80 statement.getTableElementList().forEach(element -> parseColumn(columns, element));
81 return columns; 81 return columns;
82 } 82 }
83 83
84 - private static void parseColumn(List<SchemaColumnDO> columns, SQLTableElement element) { 84 + private static void parseColumn(List<DatabaseColumnDO> columns, SQLTableElement element) {
85 // 处理主键 85 // 处理主键
86 if (element instanceof SQLPrimaryKey) { 86 if (element instanceof SQLPrimaryKey) {
87 parsePrimaryKey(columns, (SQLPrimaryKey) element); 87 parsePrimaryKey(columns, (SQLPrimaryKey) element);
@@ -93,16 +93,16 @@ public class CodegenSQLParser { @@ -93,16 +93,16 @@ public class CodegenSQLParser {
93 } 93 }
94 } 94 }
95 95
96 - private static void parsePrimaryKey(List<SchemaColumnDO> columns, SQLPrimaryKey primaryKey) { 96 + private static void parsePrimaryKey(List<DatabaseColumnDO> columns, SQLPrimaryKey primaryKey) {
97 String columnName = normalize(primaryKey.getColumns().get(0).toString()); // 暂时不考虑联合主键 97 String columnName = normalize(primaryKey.getColumns().get(0).toString()); // 暂时不考虑联合主键
98 // 匹配 columns 主键字段,设置为 primary 98 // 匹配 columns 主键字段,设置为 primary
99 columns.stream().filter(column -> column.getColumnName().equals(columnName)) 99 columns.stream().filter(column -> column.getColumnName().equals(columnName))
100 .forEach(column -> column.setPrimaryKey(true)); 100 .forEach(column -> column.setPrimaryKey(true));
101 } 101 }
102 102
103 - private static void parseColumnDefinition(List<SchemaColumnDO> columns, SQLColumnDefinition definition) { 103 + private static void parseColumnDefinition(List<DatabaseColumnDO> columns, SQLColumnDefinition definition) {
104 String text = definition.toString().toUpperCase(); 104 String text = definition.toString().toUpperCase();
105 - columns.add(SchemaColumnDO.builder() 105 + columns.add(DatabaseColumnDO.builder()
106 .columnName(normalize(definition.getColumnName())) 106 .columnName(normalize(definition.getColumnName()))
107 .columnType(definition.getDataType().toString()) 107 .columnType(definition.getDataType().toString())
108 .columnComment(Objects.isNull(definition.getComment()) ? "" 108 .columnComment(Objects.isNull(definition.getComment()) ? ""
yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/db/DataSourceConfigService.java
1 package cn.iocoder.yudao.module.infra.service.db; 1 package cn.iocoder.yudao.module.infra.service.db;
2 2
3 -import cn.iocoder.yudao.framework.common.pojo.PageResult;  
4 import cn.iocoder.yudao.module.infra.controller.admin.db.vo.DataSourceConfigCreateReqVO; 3 import cn.iocoder.yudao.module.infra.controller.admin.db.vo.DataSourceConfigCreateReqVO;
5 import cn.iocoder.yudao.module.infra.controller.admin.db.vo.DataSourceConfigUpdateReqVO; 4 import cn.iocoder.yudao.module.infra.controller.admin.db.vo.DataSourceConfigUpdateReqVO;
6 import cn.iocoder.yudao.module.infra.dal.dataobject.db.DataSourceConfigDO; 5 import cn.iocoder.yudao.module.infra.dal.dataobject.db.DataSourceConfigDO;
7 -import org.w3c.dom.stylesheets.LinkStyle; 6 +import cn.iocoder.yudao.module.infra.dal.dataobject.db.DatabaseTableDO;
8 7
9 import javax.validation.Valid; 8 import javax.validation.Valid;
10 import java.util.List; 9 import java.util.List;
yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/db/DataSourceConfigServiceImpl.java
1 package cn.iocoder.yudao.module.infra.service.db; 1 package cn.iocoder.yudao.module.infra.service.db;
2 2
3 -import cn.hutool.db.DbUtil;  
4 -import cn.iocoder.yudao.framework.common.pojo.PageResult;  
5 -import cn.iocoder.yudao.framework.mybatis.core.util.DatabaseUtils; 3 +import cn.iocoder.yudao.framework.mybatis.core.util.JdbcUtils;
6 import cn.iocoder.yudao.module.infra.controller.admin.db.vo.DataSourceConfigCreateReqVO; 4 import cn.iocoder.yudao.module.infra.controller.admin.db.vo.DataSourceConfigCreateReqVO;
7 import cn.iocoder.yudao.module.infra.controller.admin.db.vo.DataSourceConfigUpdateReqVO; 5 import cn.iocoder.yudao.module.infra.controller.admin.db.vo.DataSourceConfigUpdateReqVO;
8 import cn.iocoder.yudao.module.infra.convert.db.DataSourceConfigConvert; 6 import cn.iocoder.yudao.module.infra.convert.db.DataSourceConfigConvert;
9 import cn.iocoder.yudao.module.infra.dal.dataobject.db.DataSourceConfigDO; 7 import cn.iocoder.yudao.module.infra.dal.dataobject.db.DataSourceConfigDO;
10 import cn.iocoder.yudao.module.infra.dal.mysql.db.DataSourceConfigMapper; 8 import cn.iocoder.yudao.module.infra.dal.mysql.db.DataSourceConfigMapper;
11 -import com.baomidou.mybatisplus.extension.toolkit.JdbcUtils; 9 +import com.baomidou.dynamic.datasource.spring.boot.autoconfigure.DataSourceProperty;
  10 +import com.baomidou.dynamic.datasource.spring.boot.autoconfigure.DynamicDataSourceProperties;
12 import org.jasypt.encryption.StringEncryptor; 11 import org.jasypt.encryption.StringEncryptor;
13 import org.springframework.stereotype.Service; 12 import org.springframework.stereotype.Service;
14 import org.springframework.validation.annotation.Validated; 13 import org.springframework.validation.annotation.Validated;
15 14
16 import javax.annotation.Resource; 15 import javax.annotation.Resource;
17 16
18 -import java.sql.Connection;  
19 import java.util.List; 17 import java.util.List;
  18 +import java.util.Objects;
20 19
21 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; 20 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
22 import static cn.iocoder.yudao.module.infra.enums.ErrorCodeConstants.DATA_SOURCE_CONFIG_NOT_EXISTS; 21 import static cn.iocoder.yudao.module.infra.enums.ErrorCodeConstants.DATA_SOURCE_CONFIG_NOT_EXISTS;
@@ -37,6 +36,9 @@ public class DataSourceConfigServiceImpl implements DataSourceConfigService { @@ -37,6 +36,9 @@ public class DataSourceConfigServiceImpl implements DataSourceConfigService {
37 @Resource 36 @Resource
38 private StringEncryptor stringEncryptor; 37 private StringEncryptor stringEncryptor;
39 38
  39 + @Resource
  40 + private DynamicDataSourceProperties dynamicDataSourceProperties;
  41 +
40 @Override 42 @Override
41 public Long createDataSourceConfig(DataSourceConfigCreateReqVO createReqVO) { 43 public Long createDataSourceConfig(DataSourceConfigCreateReqVO createReqVO) {
42 DataSourceConfigDO dataSourceConfig = DataSourceConfigConvert.INSTANCE.convert(createReqVO); 44 DataSourceConfigDO dataSourceConfig = DataSourceConfigConvert.INSTANCE.convert(createReqVO);
@@ -77,6 +79,11 @@ public class DataSourceConfigServiceImpl implements DataSourceConfigService { @@ -77,6 +79,11 @@ public class DataSourceConfigServiceImpl implements DataSourceConfigService {
77 79
78 @Override 80 @Override
79 public DataSourceConfigDO getDataSourceConfig(Long id) { 81 public DataSourceConfigDO getDataSourceConfig(Long id) {
  82 + // 如果 id 为 0,默认为 master 的数据源
  83 + if (Objects.equals(id, DataSourceConfigDO.ID_MASTER)) {
  84 + return buildMasterDataSourceConfig();
  85 + }
  86 + // 从 DB 中读取
80 DataSourceConfigDO dataSourceConfig = dataSourceConfigMapper.selectById(id); 87 DataSourceConfigDO dataSourceConfig = dataSourceConfigMapper.selectById(id);
81 dataSourceConfig.setPassword(stringEncryptor.decrypt(dataSourceConfig.getPassword())); 88 dataSourceConfig.setPassword(stringEncryptor.decrypt(dataSourceConfig.getPassword()));
82 return dataSourceConfig; 89 return dataSourceConfig;
@@ -84,14 +91,26 @@ public class DataSourceConfigServiceImpl implements DataSourceConfigService { @@ -84,14 +91,26 @@ public class DataSourceConfigServiceImpl implements DataSourceConfigService {
84 91
85 @Override 92 @Override
86 public List<DataSourceConfigDO> getDataSourceConfigList() { 93 public List<DataSourceConfigDO> getDataSourceConfigList() {
87 - return dataSourceConfigMapper.selectList(); 94 + List<DataSourceConfigDO> result = dataSourceConfigMapper.selectList();
  95 + // 补充 master 数据源
  96 + result.add(0, buildMasterDataSourceConfig());
  97 + return result;
88 } 98 }
89 99
90 private void checkConnectionOK(DataSourceConfigDO config) { 100 private void checkConnectionOK(DataSourceConfigDO config) {
91 - boolean success = DatabaseUtils.isConnectionOK(config.getUrl(), config.getUsername(), config.getPassword()); 101 + boolean success = JdbcUtils.isConnectionOK(config.getUrl(), config.getUsername(), config.getPassword());
92 if (!success) { 102 if (!success) {
93 throw exception(DATA_SOURCE_CONFIG_NOT_OK); 103 throw exception(DATA_SOURCE_CONFIG_NOT_OK);
94 } 104 }
95 } 105 }
96 106
  107 + private DataSourceConfigDO buildMasterDataSourceConfig() {
  108 + String primary = dynamicDataSourceProperties.getPrimary();
  109 + DataSourceProperty dataSourceProperty = dynamicDataSourceProperties.getDatasource().get(primary);
  110 + return new DataSourceConfigDO().setId(DataSourceConfigDO.ID_MASTER).setName(primary)
  111 + .setUrl(dataSourceProperty.getUrl())
  112 + .setUsername(dataSourceProperty.getUsername())
  113 + .setPassword(dataSourceProperty.getPassword());
  114 + }
  115 +
97 } 116 }
yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/db/DatabaseTableService.java 0 → 100644
  1 +package cn.iocoder.yudao.module.infra.service.db;
  2 +
  3 +import cn.iocoder.yudao.module.infra.dal.dataobject.db.DatabaseColumnDO;
  4 +import cn.iocoder.yudao.module.infra.dal.dataobject.db.DatabaseTableDO;
  5 +
  6 +import java.util.List;
  7 +
  8 +/**
  9 + * 数据库表 Service
  10 + *
  11 + * @author 芋道源码
  12 + */
  13 +public interface DatabaseTableService {
  14 +
  15 + /**
  16 + * 获得表列表,基于表名称 + 表描述进行模糊匹配
  17 + *
  18 + * @param dataSourceConfigId 数据源配置的编号
  19 + * @param tableNameLike 表名称,模糊匹配
  20 + * @param tableCommentLike 表描述,模糊匹配
  21 + * @return 表列表
  22 + */
  23 + List<DatabaseTableDO> getTableList(Long dataSourceConfigId, String tableNameLike, String tableCommentLike);
  24 +
  25 + /**
  26 + * 获得指定表名
  27 + *
  28 + * @param dataSourceConfigId 数据源配置的编号
  29 + * @param tableName 表名称
  30 + * @return 表
  31 + */
  32 + DatabaseTableDO getTable(Long dataSourceConfigId, String tableName);
  33 +
  34 + /**
  35 + * 获得指定表的字段列表
  36 + *
  37 + * @param dataSourceConfigId 数据源配置的编号
  38 + * @param tableName 表名称
  39 + * @return 字段列表
  40 + */
  41 + List<DatabaseColumnDO> getColumnList(Long dataSourceConfigId, String tableName);
  42 +
  43 +}
yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/db/DatabaseTableServiceImpl.java 0 → 100644
  1 +package cn.iocoder.yudao.module.infra.service.db;
  2 +
  3 +import cn.hutool.core.collection.CollUtil;
  4 +import cn.hutool.core.lang.Assert;
  5 +import cn.iocoder.yudao.framework.mybatis.core.util.JdbcUtils;
  6 +import cn.iocoder.yudao.module.infra.dal.dataobject.db.DataSourceConfigDO;
  7 +import cn.iocoder.yudao.module.infra.dal.dataobject.db.DatabaseColumnDO;
  8 +import cn.iocoder.yudao.module.infra.dal.dataobject.db.DatabaseTableDO;
  9 +import cn.iocoder.yudao.module.infra.dal.mysql.db.DatabaseTableDAO;
  10 +import com.baomidou.mybatisplus.annotation.DbType;
  11 +import lombok.SneakyThrows;
  12 +import org.springframework.stereotype.Service;
  13 +
  14 +import javax.annotation.Resource;
  15 +import java.sql.Connection;
  16 +import java.util.List;
  17 +
  18 +/**
  19 + * 数据库表 Service 实现类
  20 + *
  21 + * @author 芋道源码
  22 + */
  23 +@Service
  24 +public class DatabaseTableServiceImpl implements DatabaseTableService {
  25 +
  26 + @Resource
  27 + private DataSourceConfigService dataSourceConfigService;
  28 +
  29 + @Resource
  30 + private List<DatabaseTableDAO> databaseTableDAOs;
  31 +
  32 + @Override
  33 + @SneakyThrows
  34 + public List<DatabaseTableDO> getTableList(Long dataSourceConfigId, String tableNameLike, String tableCommentLike) {
  35 + try (Connection connection = getConnection(dataSourceConfigId)) {
  36 + return getDatabaseTableDAO(dataSourceConfigId).selectTableList(connection, tableNameLike, tableCommentLike);
  37 + }
  38 + }
  39 +
  40 + @Override
  41 + @SneakyThrows
  42 + public DatabaseTableDO getTable(Long dataSourceConfigId, String tableName) {
  43 + try (Connection connection = getConnection(dataSourceConfigId)) {
  44 + return getDatabaseTableDAO(dataSourceConfigId).selectTable(connection, tableName);
  45 + }
  46 + }
  47 +
  48 + @Override
  49 + @SneakyThrows
  50 + public List<DatabaseColumnDO> getColumnList(Long dataSourceConfigId, String tableName) {
  51 + try (Connection connection = getConnection(dataSourceConfigId)) {
  52 + return getDatabaseTableDAO(dataSourceConfigId).selectColumnList(connection, tableName);
  53 + }
  54 + }
  55 +
  56 + private Connection getConnection(Long dataSourceConfigId) {
  57 + DataSourceConfigDO config = dataSourceConfigService.getDataSourceConfig(dataSourceConfigId);
  58 + Assert.notNull(config, "数据源({}) 不存在!", dataSourceConfigId);
  59 + return JdbcUtils.getConnection(config.getUrl(), config.getUsername(), config.getPassword());
  60 + }
  61 +
  62 + private DatabaseTableDAO getDatabaseTableDAO(Long dataSourceConfigId) {
  63 + DataSourceConfigDO config = dataSourceConfigService.getDataSourceConfig(dataSourceConfigId);
  64 + Assert.notNull(config, "数据源({}) 不存在!", dataSourceConfigId);
  65 + // 获得 dbType
  66 + DbType dbType = JdbcUtils.getDbType(config.getUrl());
  67 + Assert.notNull(config, "数据源类型({}) 不存在!", config.getUrl());
  68 + // 获得 DatabaseTableDAO
  69 + DatabaseTableDAO dao = CollUtil.findOne(databaseTableDAOs, databaseTableDAO -> databaseTableDAO.getType().equals(dbType));
  70 + Assert.notNull(dao, "DAO({}) 查找不到实现!", dbType);
  71 + return dao;
  72 + }
  73 +
  74 +}
yudao-module-infra/yudao-module-infra-biz/src/test/java/cn/iocoder/yudao/module/infra/service/db/DataSourceConfigServiceImplTest.java
1 package cn.iocoder.yudao.module.infra.service.db; 1 package cn.iocoder.yudao.module.infra.service.db;
2 2
3 -import cn.iocoder.yudao.framework.mybatis.core.util.DatabaseUtils; 3 +import cn.iocoder.yudao.framework.mybatis.core.util.JdbcUtils;
4 import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest; 4 import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest;
5 import cn.iocoder.yudao.module.infra.controller.admin.db.vo.DataSourceConfigCreateReqVO; 5 import cn.iocoder.yudao.module.infra.controller.admin.db.vo.DataSourceConfigCreateReqVO;
6 import cn.iocoder.yudao.module.infra.controller.admin.db.vo.DataSourceConfigUpdateReqVO; 6 import cn.iocoder.yudao.module.infra.controller.admin.db.vo.DataSourceConfigUpdateReqVO;
@@ -41,12 +41,12 @@ public class DataSourceConfigServiceImplTest extends BaseDbUnitTest { @@ -41,12 +41,12 @@ public class DataSourceConfigServiceImplTest extends BaseDbUnitTest {
41 41
42 @Test 42 @Test
43 public void testCreateDataSourceConfig_success() { 43 public void testCreateDataSourceConfig_success() {
44 - try (MockedStatic<DatabaseUtils> databaseUtilsMock = mockStatic(DatabaseUtils.class)) { 44 + try (MockedStatic<JdbcUtils> databaseUtilsMock = mockStatic(JdbcUtils.class)) {
45 // 准备参数 45 // 准备参数
46 DataSourceConfigCreateReqVO reqVO = randomPojo(DataSourceConfigCreateReqVO.class); 46 DataSourceConfigCreateReqVO reqVO = randomPojo(DataSourceConfigCreateReqVO.class);
47 // mock 方法 47 // mock 方法
48 when(stringEncryptor.encrypt(eq(reqVO.getPassword()))).thenReturn("123456"); 48 when(stringEncryptor.encrypt(eq(reqVO.getPassword()))).thenReturn("123456");
49 - databaseUtilsMock.when(() -> DatabaseUtils.isConnectionOK(eq(reqVO.getUrl()), 49 + databaseUtilsMock.when(() -> JdbcUtils.isConnectionOK(eq(reqVO.getUrl()),
50 eq(reqVO.getUsername()), eq(reqVO.getPassword()))).thenReturn(true); 50 eq(reqVO.getUsername()), eq(reqVO.getPassword()))).thenReturn(true);
51 51
52 // 调用 52 // 调用
@@ -62,7 +62,7 @@ public class DataSourceConfigServiceImplTest extends BaseDbUnitTest { @@ -62,7 +62,7 @@ public class DataSourceConfigServiceImplTest extends BaseDbUnitTest {
62 62
63 @Test 63 @Test
64 public void testUpdateDataSourceConfig_success() { 64 public void testUpdateDataSourceConfig_success() {
65 - try (MockedStatic<DatabaseUtils> databaseUtilsMock = mockStatic(DatabaseUtils.class)) { 65 + try (MockedStatic<JdbcUtils> databaseUtilsMock = mockStatic(JdbcUtils.class)) {
66 // mock 数据 66 // mock 数据
67 DataSourceConfigDO dbDataSourceConfig = randomPojo(DataSourceConfigDO.class); 67 DataSourceConfigDO dbDataSourceConfig = randomPojo(DataSourceConfigDO.class);
68 dataSourceConfigMapper.insert(dbDataSourceConfig);// @Sql: 先插入出一条存在的数据 68 dataSourceConfigMapper.insert(dbDataSourceConfig);// @Sql: 先插入出一条存在的数据
@@ -72,7 +72,7 @@ public class DataSourceConfigServiceImplTest extends BaseDbUnitTest { @@ -72,7 +72,7 @@ public class DataSourceConfigServiceImplTest extends BaseDbUnitTest {
72 }); 72 });
73 // mock 方法 73 // mock 方法
74 when(stringEncryptor.encrypt(eq(reqVO.getPassword()))).thenReturn("123456"); 74 when(stringEncryptor.encrypt(eq(reqVO.getPassword()))).thenReturn("123456");
75 - databaseUtilsMock.when(() -> DatabaseUtils.isConnectionOK(eq(reqVO.getUrl()), 75 + databaseUtilsMock.when(() -> JdbcUtils.isConnectionOK(eq(reqVO.getUrl()),
76 eq(reqVO.getUsername()), eq(reqVO.getPassword()))).thenReturn(true); 76 eq(reqVO.getUsername()), eq(reqVO.getPassword()))).thenReturn(true);
77 77
78 // 调用 78 // 调用