Commit d79549b48a635c856f8b8c26b1d2155f56163096
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 | 13 | import cn.iocoder.yudao.module.infra.convert.codegen.CodegenConvert; |
| 14 | 14 | import cn.iocoder.yudao.module.infra.dal.dataobject.codegen.CodegenColumnDO; |
| 15 | 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 | 17 | import cn.iocoder.yudao.module.infra.service.codegen.CodegenService; |
| 18 | 18 | import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; |
| 19 | 19 | import cn.iocoder.yudao.framework.common.util.servlet.ServletUtils; |
| ... | ... | @@ -58,7 +58,7 @@ public class CodegenController { |
| 58 | 58 | @RequestParam(value = "tableName", required = false) String tableName, |
| 59 | 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 | 62 | // 移除在 Codegen 中,已经存在的 |
| 63 | 63 | Set<String> existsTables = CollectionUtils.convertSet(codegenService.getCodeGenTableList(), CodegenTableDO::getTableName); |
| 64 | 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 | 9 | import cn.iocoder.yudao.module.infra.controller.admin.codegen.vo.table.SchemaTableRespVO; |
| 10 | 10 | import cn.iocoder.yudao.module.infra.dal.dataobject.codegen.CodegenColumnDO; |
| 11 | 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 | 14 | import org.mapstruct.Mapper; |
| 15 | 15 | import org.mapstruct.factory.Mappers; |
| 16 | 16 | |
| ... | ... | @@ -25,11 +25,11 @@ public interface CodegenConvert { |
| 25 | 25 | |
| 26 | 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 | 34 | // ========== CodegenTableDO 相关 ========== |
| 35 | 35 | |
| ... | ... | @@ -47,7 +47,7 @@ public interface CodegenConvert { |
| 47 | 47 | |
| 48 | 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
yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/dataobject/db/DataSourceConfigDO.java
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 | 3 | import com.baomidou.mybatisplus.annotation.TableField; |
| 4 | 4 | import com.baomidou.mybatisplus.annotation.TableName; |
| ... | ... | @@ -10,10 +10,9 @@ import lombok.Data; |
| 10 | 10 | * |
| 11 | 11 | * @author 芋道源码 |
| 12 | 12 | */ |
| 13 | -@TableName(value = "information_schema.columns", autoResultMap = true) | |
| 14 | 13 | @Data |
| 15 | 14 | @Builder |
| 16 | -public class SchemaColumnDO { | |
| 15 | +public class DatabaseColumnDO { | |
| 17 | 16 | |
| 18 | 17 | /** |
| 19 | 18 | * 表名称 |
| ... | ... | @@ -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 | 36 | private Boolean nullable; |
| 39 | 37 | /** |
| 40 | 38 | * 是否主键 |
| 41 | 39 | */ |
| 42 | - @TableField("case when column_key = 'PRI' then '1' else '0' end") | |
| 43 | 40 | private Boolean primaryKey; |
| 44 | 41 | /** |
| 45 | 42 | * 是否自增 |
| 46 | 43 | */ |
| 47 | - @TableField("case when extra = 'auto_increment' then '1' else '0' end") | |
| 48 | 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 | 3 | import lombok.Builder; |
| 5 | 4 | import lombok.Data; |
| 6 | 5 | |
| ... | ... | @@ -11,16 +10,11 @@ import java.util.Date; |
| 11 | 10 | * |
| 12 | 11 | * @author 芋道源码 |
| 13 | 12 | */ |
| 14 | -@TableName(value = "information_schema.tables", autoResultMap = true) | |
| 15 | 13 | @Data |
| 16 | 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 | 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 | 5 | import cn.iocoder.yudao.module.infra.controller.admin.codegen.vo.table.CodegenTablePageReqVO; |
| 6 | 6 | import cn.iocoder.yudao.module.infra.dal.dataobject.codegen.CodegenColumnDO; |
| 7 | 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 | 10 | import java.util.List; |
| 11 | 11 | import java.util.Map; |
| ... | ... | @@ -119,6 +119,6 @@ public interface CodegenService { |
| 119 | 119 | * @param tableComment 表描述 |
| 120 | 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 | 8 | import cn.iocoder.yudao.module.infra.convert.codegen.CodegenConvert; |
| 9 | 9 | import cn.iocoder.yudao.module.infra.dal.dataobject.codegen.CodegenColumnDO; |
| 10 | 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 | 13 | import cn.iocoder.yudao.module.infra.dal.mysql.codegen.CodegenColumnMapper; |
| 14 | 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 | 15 | import cn.iocoder.yudao.module.infra.enums.codegen.CodegenImportTypeEnum; |
| 18 | 16 | import cn.iocoder.yudao.module.infra.framework.codegen.config.CodegenProperties; |
| 19 | 17 | import cn.iocoder.yudao.module.infra.service.codegen.inner.CodegenBuilder; |
| 20 | 18 | import cn.iocoder.yudao.module.infra.service.codegen.inner.CodegenEngine; |
| 21 | 19 | import cn.iocoder.yudao.module.infra.service.codegen.inner.CodegenSQLParser; |
| 20 | +import cn.iocoder.yudao.module.infra.service.db.DatabaseTableService; | |
| 22 | 21 | import cn.iocoder.yudao.module.system.api.user.AdminUserApi; |
| 23 | 22 | import org.apache.commons.collections4.KeyValue; |
| 24 | 23 | import org.springframework.stereotype.Service; |
| ... | ... | @@ -43,9 +42,8 @@ import static cn.iocoder.yudao.module.infra.enums.ErrorCodeConstants.*; |
| 43 | 42 | public class CodegenServiceImpl implements CodegenService { |
| 44 | 43 | |
| 45 | 44 | @Resource |
| 46 | - private SchemaTableMapper schemaTableMapper; | |
| 47 | - @Resource | |
| 48 | - private SchemaColumnMapper schemaColumnMapper; | |
| 45 | + private DatabaseTableService databaseTableService; | |
| 46 | + | |
| 49 | 47 | @Resource |
| 50 | 48 | private CodegenTableMapper codegenTableMapper; |
| 51 | 49 | @Resource |
| ... | ... | @@ -63,7 +61,7 @@ public class CodegenServiceImpl implements CodegenService { |
| 63 | 61 | private CodegenProperties codegenProperties; |
| 64 | 62 | |
| 65 | 63 | private Long createCodegen0(Long userId, CodegenImportTypeEnum importType, |
| 66 | - SchemaTableDO schemaTable, List<SchemaColumnDO> schemaColumns) { | |
| 64 | + DatabaseTableDO schemaTable, List<DatabaseColumnDO> schemaColumns) { | |
| 67 | 65 | // 校验导入的表和字段非空 |
| 68 | 66 | if (schemaTable == null) { |
| 69 | 67 | throw exception(CODEGEN_IMPORT_TABLE_NULL); |
| ... | ... | @@ -90,10 +88,10 @@ public class CodegenServiceImpl implements CodegenService { |
| 90 | 88 | @Override |
| 91 | 89 | public Long createCodegenListFromSQL(Long userId, String sql) { |
| 92 | 90 | // 从 SQL 中,获得数据库表结构 |
| 93 | - SchemaTableDO schemaTable; | |
| 94 | - List<SchemaColumnDO> schemaColumns; | |
| 91 | + DatabaseTableDO schemaTable; | |
| 92 | + List<DatabaseColumnDO> schemaColumns; | |
| 95 | 93 | try { |
| 96 | - KeyValue<SchemaTableDO, List<SchemaColumnDO>> result = CodegenSQLParser.parse(sql); | |
| 94 | + KeyValue<DatabaseTableDO, List<DatabaseColumnDO>> result = CodegenSQLParser.parse(sql); | |
| 97 | 95 | schemaTable = result.getKey(); |
| 98 | 96 | schemaColumns = result.getValue(); |
| 99 | 97 | } catch (Exception ex) { |
| ... | ... | @@ -108,8 +106,8 @@ public class CodegenServiceImpl implements CodegenService { |
| 108 | 106 | // 获取当前schema |
| 109 | 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 | 112 | return this.createCodegen0(userId, CodegenImportTypeEnum.DB, schemaTable, schemaColumns); |
| 115 | 113 | } |
| ... | ... | @@ -147,9 +145,8 @@ public class CodegenServiceImpl implements CodegenService { |
| 147 | 145 | if (table == null) { |
| 148 | 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 | 152 | this.syncCodegen0(tableId, schemaColumns); |
| ... | ... | @@ -164,9 +161,9 @@ public class CodegenServiceImpl implements CodegenService { |
| 164 | 161 | throw exception(CODEGEN_TABLE_NOT_EXISTS); |
| 165 | 162 | } |
| 166 | 163 | // 从 SQL 中,获得数据库表结构 |
| 167 | - List<SchemaColumnDO> schemaColumns; | |
| 164 | + List<DatabaseColumnDO> schemaColumns; | |
| 168 | 165 | try { |
| 169 | - KeyValue<SchemaTableDO, List<SchemaColumnDO>> result = CodegenSQLParser.parse(sql); | |
| 166 | + KeyValue<DatabaseTableDO, List<DatabaseColumnDO>> result = CodegenSQLParser.parse(sql); | |
| 170 | 167 | schemaColumns = result.getValue(); |
| 171 | 168 | } catch (Exception ex) { |
| 172 | 169 | throw exception(CODEGEN_PARSE_SQL_ERROR); |
| ... | ... | @@ -176,12 +173,12 @@ public class CodegenServiceImpl implements CodegenService { |
| 176 | 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 | 178 | if (CollUtil.isEmpty(schemaColumns)) { |
| 182 | 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 | 183 | // 构建 CodegenColumnDO 数组,只同步新增的字段 |
| 187 | 184 | List<CodegenColumnDO> codegenColumns = codegenColumnMapper.selectListByTableId(tableId); |
| ... | ... | @@ -255,8 +252,8 @@ public class CodegenServiceImpl implements CodegenService { |
| 255 | 252 | } |
| 256 | 253 | |
| 257 | 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 | 257 | // TODO 强制移除 Quartz 的表,未来做成可配置 |
| 261 | 258 | tables.removeIf(table -> table.getTableName().startsWith("QRTZ_")); |
| 262 | 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 | 7 | import cn.iocoder.yudao.module.infra.convert.codegen.CodegenConvert; |
| 8 | 8 | import cn.iocoder.yudao.module.infra.dal.dataobject.codegen.CodegenColumnDO; |
| 9 | 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 | 12 | import cn.iocoder.yudao.module.infra.enums.codegen.CodegenColumnHtmlTypeEnum; |
| 13 | 13 | import cn.iocoder.yudao.module.infra.enums.codegen.CodegenColumnListConditionEnum; |
| 14 | 14 | import cn.iocoder.yudao.module.infra.enums.codegen.CodegenTemplateTypeEnum; |
| ... | ... | @@ -22,8 +22,8 @@ import static cn.hutool.core.text.CharSequenceUtil.*; |
| 22 | 22 | |
| 23 | 23 | /** |
| 24 | 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 | 28 | @Component |
| 29 | 29 | public class CodegenBuilder { |
| ... | ... | @@ -109,7 +109,7 @@ public class CodegenBuilder { |
| 109 | 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 | 113 | CodegenTableDO table = CodegenConvert.INSTANCE.convert(schemaTable); |
| 114 | 114 | initTableDefault(table); |
| 115 | 115 | return table; |
| ... | ... | @@ -133,7 +133,7 @@ public class CodegenBuilder { |
| 133 | 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 | 137 | List<CodegenColumnDO> columns = CodegenConvert.INSTANCE.convertList(schemaColumns); |
| 138 | 138 | for (CodegenColumnDO column : columns) { |
| 139 | 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 | 1 | package cn.iocoder.yudao.module.infra.service.codegen.inner; |
| 2 | 2 | |
| 3 | 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 | 6 | import com.alibaba.druid.DbType; |
| 7 | 7 | import com.alibaba.druid.sql.ast.expr.SQLCharExpr; |
| 8 | 8 | import com.alibaba.druid.sql.ast.statement.SQLColumnDefinition; |
| ... | ... | @@ -21,7 +21,7 @@ import java.util.Objects; |
| 21 | 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 | 27 | * @author 芋道源码 |
| ... | ... | @@ -29,18 +29,18 @@ import static com.alibaba.druid.sql.SQLUtils.normalize; |
| 29 | 29 | public class CodegenSQLParser { |
| 30 | 30 | |
| 31 | 31 | /** |
| 32 | - * 解析建表 SQL 语句,返回 {@link SchemaTableDO} 和 {@link SchemaColumnDO} 对象 | |
| 32 | + * 解析建表 SQL 语句,返回 {@link DatabaseTableDO} 和 {@link DatabaseColumnDO} 对象 | |
| 33 | 33 | * |
| 34 | 34 | * @param sql 建表 SQL 语句 |
| 35 | 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 | 38 | // 解析 SQL 成 Statement |
| 39 | 39 | SQLCreateTableStatement statement = parseCreateSQL(sql); |
| 40 | 40 | // 解析 Table 表 |
| 41 | - SchemaTableDO table = parseTable(statement); | |
| 41 | + DatabaseTableDO table = parseTable(statement); | |
| 42 | 42 | // 解析 Column 字段 |
| 43 | - List<SchemaColumnDO> columns = parseColumns(statement); | |
| 43 | + List<DatabaseColumnDO> columns = parseColumns(statement); | |
| 44 | 44 | columns.forEach(column -> column.setTableName(table.getTableName())); |
| 45 | 45 | // 返回 |
| 46 | 46 | return new DefaultKeyValue<>(table, columns); |
| ... | ... | @@ -61,8 +61,8 @@ public class CodegenSQLParser { |
| 61 | 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 | 66 | .tableName(statement.getTableSource().getTableName(true)) |
| 67 | 67 | .tableComment(getCommentText(statement)) |
| 68 | 68 | .build(); |
| ... | ... | @@ -75,13 +75,13 @@ public class CodegenSQLParser { |
| 75 | 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 | 80 | statement.getTableElementList().forEach(element -> parseColumn(columns, element)); |
| 81 | 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 | 86 | if (element instanceof SQLPrimaryKey) { |
| 87 | 87 | parsePrimaryKey(columns, (SQLPrimaryKey) element); |
| ... | ... | @@ -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 | 97 | String columnName = normalize(primaryKey.getColumns().get(0).toString()); // 暂时不考虑联合主键 |
| 98 | 98 | // 匹配 columns 主键字段,设置为 primary |
| 99 | 99 | columns.stream().filter(column -> column.getColumnName().equals(columnName)) |
| 100 | 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 | 104 | String text = definition.toString().toUpperCase(); |
| 105 | - columns.add(SchemaColumnDO.builder() | |
| 105 | + columns.add(DatabaseColumnDO.builder() | |
| 106 | 106 | .columnName(normalize(definition.getColumnName())) |
| 107 | 107 | .columnType(definition.getDataType().toString()) |
| 108 | 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 | 1 | package cn.iocoder.yudao.module.infra.service.db; |
| 2 | 2 | |
| 3 | -import cn.iocoder.yudao.framework.common.pojo.PageResult; | |
| 4 | 3 | import cn.iocoder.yudao.module.infra.controller.admin.db.vo.DataSourceConfigCreateReqVO; |
| 5 | 4 | import cn.iocoder.yudao.module.infra.controller.admin.db.vo.DataSourceConfigUpdateReqVO; |
| 6 | 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 | 8 | import javax.validation.Valid; |
| 10 | 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 | 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 | 4 | import cn.iocoder.yudao.module.infra.controller.admin.db.vo.DataSourceConfigCreateReqVO; |
| 7 | 5 | import cn.iocoder.yudao.module.infra.controller.admin.db.vo.DataSourceConfigUpdateReqVO; |
| 8 | 6 | import cn.iocoder.yudao.module.infra.convert.db.DataSourceConfigConvert; |
| 9 | 7 | import cn.iocoder.yudao.module.infra.dal.dataobject.db.DataSourceConfigDO; |
| 10 | 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 | 11 | import org.jasypt.encryption.StringEncryptor; |
| 13 | 12 | import org.springframework.stereotype.Service; |
| 14 | 13 | import org.springframework.validation.annotation.Validated; |
| 15 | 14 | |
| 16 | 15 | import javax.annotation.Resource; |
| 17 | 16 | |
| 18 | -import java.sql.Connection; | |
| 19 | 17 | import java.util.List; |
| 18 | +import java.util.Objects; | |
| 20 | 19 | |
| 21 | 20 | import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; |
| 22 | 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 | 36 | @Resource |
| 38 | 37 | private StringEncryptor stringEncryptor; |
| 39 | 38 | |
| 39 | + @Resource | |
| 40 | + private DynamicDataSourceProperties dynamicDataSourceProperties; | |
| 41 | + | |
| 40 | 42 | @Override |
| 41 | 43 | public Long createDataSourceConfig(DataSourceConfigCreateReqVO createReqVO) { |
| 42 | 44 | DataSourceConfigDO dataSourceConfig = DataSourceConfigConvert.INSTANCE.convert(createReqVO); |
| ... | ... | @@ -77,6 +79,11 @@ public class DataSourceConfigServiceImpl implements DataSourceConfigService { |
| 77 | 79 | |
| 78 | 80 | @Override |
| 79 | 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 | 87 | DataSourceConfigDO dataSourceConfig = dataSourceConfigMapper.selectById(id); |
| 81 | 88 | dataSourceConfig.setPassword(stringEncryptor.decrypt(dataSourceConfig.getPassword())); |
| 82 | 89 | return dataSourceConfig; |
| ... | ... | @@ -84,14 +91,26 @@ public class DataSourceConfigServiceImpl implements DataSourceConfigService { |
| 84 | 91 | |
| 85 | 92 | @Override |
| 86 | 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 | 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 | 102 | if (!success) { |
| 93 | 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 | 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 | 4 | import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest; |
| 5 | 5 | import cn.iocoder.yudao.module.infra.controller.admin.db.vo.DataSourceConfigCreateReqVO; |
| 6 | 6 | import cn.iocoder.yudao.module.infra.controller.admin.db.vo.DataSourceConfigUpdateReqVO; |
| ... | ... | @@ -41,12 +41,12 @@ public class DataSourceConfigServiceImplTest extends BaseDbUnitTest { |
| 41 | 41 | |
| 42 | 42 | @Test |
| 43 | 43 | public void testCreateDataSourceConfig_success() { |
| 44 | - try (MockedStatic<DatabaseUtils> databaseUtilsMock = mockStatic(DatabaseUtils.class)) { | |
| 44 | + try (MockedStatic<JdbcUtils> databaseUtilsMock = mockStatic(JdbcUtils.class)) { | |
| 45 | 45 | // 准备参数 |
| 46 | 46 | DataSourceConfigCreateReqVO reqVO = randomPojo(DataSourceConfigCreateReqVO.class); |
| 47 | 47 | // mock 方法 |
| 48 | 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 | 50 | eq(reqVO.getUsername()), eq(reqVO.getPassword()))).thenReturn(true); |
| 51 | 51 | |
| 52 | 52 | // 调用 |
| ... | ... | @@ -62,7 +62,7 @@ public class DataSourceConfigServiceImplTest extends BaseDbUnitTest { |
| 62 | 62 | |
| 63 | 63 | @Test |
| 64 | 64 | public void testUpdateDataSourceConfig_success() { |
| 65 | - try (MockedStatic<DatabaseUtils> databaseUtilsMock = mockStatic(DatabaseUtils.class)) { | |
| 65 | + try (MockedStatic<JdbcUtils> databaseUtilsMock = mockStatic(JdbcUtils.class)) { | |
| 66 | 66 | // mock 数据 |
| 67 | 67 | DataSourceConfigDO dbDataSourceConfig = randomPojo(DataSourceConfigDO.class); |
| 68 | 68 | dataSourceConfigMapper.insert(dbDataSourceConfig);// @Sql: 先插入出一条存在的数据 |
| ... | ... | @@ -72,7 +72,7 @@ public class DataSourceConfigServiceImplTest extends BaseDbUnitTest { |
| 72 | 72 | }); |
| 73 | 73 | // mock 方法 |
| 74 | 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 | 76 | eq(reqVO.getUsername()), eq(reqVO.getPassword()))).thenReturn(true); |
| 77 | 77 | |
| 78 | 78 | // 调用 | ... | ... |