Commit 0be7138eefe3f3922765f8e5b3aef04eb7f4c09b
1 parent
58f83a2b
实现数据库字段的解析
Showing
12 changed files
with
310 additions
and
297 deletions
ruoyi-common/src/main/java/com/ruoyi/common/constant/GenConstants.java
| ... | ... | @@ -33,81 +33,8 @@ public class GenConstants { |
| 33 | 33 | public static final String PARENT_MENU_NAME = "parentMenuName"; |
| 34 | 34 | |
| 35 | 35 | /** |
| 36 | - * 数据库字符串类型 | |
| 37 | - */ | |
| 38 | - public static final String[] COLUMNTYPE_STR = {"char", "varchar", "nvarchar", "varchar2"}; | |
| 39 | - | |
| 40 | - /** | |
| 41 | - * 数据库文本类型 | |
| 42 | - */ | |
| 43 | - public static final String[] COLUMNTYPE_TEXT = {"tinytext", "text", "mediumtext", "longtext"}; | |
| 44 | - | |
| 45 | - /** | |
| 46 | - * 数据库时间类型 | |
| 47 | - */ | |
| 48 | - public static final String[] COLUMNTYPE_TIME = {"datetime", "time", "date", "timestamp"}; | |
| 49 | - | |
| 50 | - /** | |
| 51 | - * 数据库数字类型 | |
| 52 | - */ | |
| 53 | - public static final String[] COLUMNTYPE_NUMBER = {"tinyint", "smallint", "mediumint", "int", "number", "integer", | |
| 54 | - "bit", "bigint", "float", "double", "decimal"}; | |
| 55 | - | |
| 56 | - /** | |
| 57 | - * 页面不需要编辑字段 | |
| 58 | - */ | |
| 59 | - public static final String[] COLUMNNAME_NOT_EDIT = {"id", "create_by", "create_time", "del_flag"}; | |
| 60 | - | |
| 61 | - /** | |
| 62 | - * 页面不需要显示的列表字段 | |
| 63 | - */ | |
| 64 | - public static final String[] COLUMNNAME_NOT_LIST = {"id", "create_by", "create_time", "del_flag", "update_by", | |
| 65 | - "update_time"}; | |
| 66 | - | |
| 67 | - /** | |
| 68 | - * 页面不需要查询字段 | |
| 69 | - */ | |
| 70 | - public static final String[] COLUMNNAME_NOT_QUERY = {"id", "create_by", "create_time", "del_flag", "update_by", | |
| 71 | - "update_time", "remark"}; | |
| 72 | - | |
| 73 | - /** | |
| 74 | - * Entity基类字段 | |
| 75 | - */ | |
| 76 | - public static final String[] BASE_ENTITY = {"createBy", "createTime", "updateBy", "updateTime", "remark"}; | |
| 77 | - | |
| 78 | - /** | |
| 79 | 36 | * Tree基类字段 |
| 80 | 37 | */ |
| 81 | 38 | public static final String[] TREE_ENTITY = {"parentName", "parentId", "orderNum", "ancestors", "children"}; |
| 82 | 39 | |
| 83 | - /** | |
| 84 | - * 字符串类型 | |
| 85 | - */ | |
| 86 | - public static final String TYPE_STRING = "String"; | |
| 87 | - | |
| 88 | - /** | |
| 89 | - * 整型 | |
| 90 | - */ | |
| 91 | - public static final String TYPE_INTEGER = "Integer"; | |
| 92 | - | |
| 93 | - /** | |
| 94 | - * 长整型 | |
| 95 | - */ | |
| 96 | - public static final String TYPE_LONG = "Long"; | |
| 97 | - | |
| 98 | - /** | |
| 99 | - * 浮点型 | |
| 100 | - */ | |
| 101 | - public static final String TYPE_DOUBLE = "Double"; | |
| 102 | - | |
| 103 | - /** | |
| 104 | - * 高精度计算类型 | |
| 105 | - */ | |
| 106 | - public static final String TYPE_BIGDECIMAL = "BigDecimal"; | |
| 107 | - | |
| 108 | - /** | |
| 109 | - * 时间类型 | |
| 110 | - */ | |
| 111 | - public static final String TYPE_DATE = "Date"; | |
| 112 | - | |
| 113 | 40 | } | ... | ... |
ruoyi-generator/src/main/java/com/ruoyi/generator/util/GenUtils.java deleted
| 1 | -package com.ruoyi.generator.util; | |
| 2 | - | |
| 3 | -import java.util.Arrays; | |
| 4 | - | |
| 5 | -import org.apache.commons.lang3.RegExUtils; | |
| 6 | -import com.ruoyi.common.constant.GenConstants; | |
| 7 | -import com.ruoyi.common.utils.StringUtils; | |
| 8 | -import com.ruoyi.generator.config.GenConfig; | |
| 9 | -import com.ruoyi.generator.domain.GenTable; | |
| 10 | -import com.ruoyi.generator.domain.GenTableColumn; | |
| 11 | - | |
| 12 | -/** | |
| 13 | - * 代码生成器 工具类 | |
| 14 | - * | |
| 15 | - * @author ruoyi | |
| 16 | - */ | |
| 17 | -public class GenUtils { | |
| 18 | - /** | |
| 19 | - * 初始化表信息 | |
| 20 | - */ | |
| 21 | - public static void initTable(GenTable genTable, String operName) { | |
| 22 | - genTable.setClassName(convertClassName(genTable.getTableName())); | |
| 23 | - genTable.setPackageName(GenConfig.getPackageName()); | |
| 24 | - genTable.setModuleName(getModuleName(GenConfig.getPackageName())); | |
| 25 | - genTable.setBusinessName(getBusinessName(genTable.getTableName())); | |
| 26 | - genTable.setFunctionName(replaceText(genTable.getTableComment())); | |
| 27 | - genTable.setFunctionAuthor(GenConfig.getAuthor()); | |
| 28 | - genTable.setCreateBy(operName); | |
| 29 | - } | |
| 30 | - | |
| 31 | - /** | |
| 32 | - * 初始化列属性字段 | |
| 33 | - */ | |
| 34 | - public static void initColumnField(GenTableColumn column, GenTable table) { | |
| 35 | - String dataType = getDbType(column.getColumnType()); | |
| 36 | - String columnName = column.getColumnName(); | |
| 37 | - column.setTableId(table.getTableId()); | |
| 38 | - column.setCreateBy(table.getCreateBy()); | |
| 39 | - // 设置java字段名 | |
| 40 | - column.setJavaField(StringUtils.toCamelCase(columnName)); | |
| 41 | - // 设置默认类型 | |
| 42 | - column.setJavaType(GenConstants.TYPE_STRING); | |
| 43 | - | |
| 44 | - if (arraysContains(GenConstants.COLUMNTYPE_STR, dataType) || arraysContains(GenConstants.COLUMNTYPE_TEXT, dataType)) { | |
| 45 | - // 字符串长度超过500设置为文本域 | |
| 46 | - Integer columnLength = getColumnLength(column.getColumnType()); | |
| 47 | - String htmlType = columnLength >= 500 || arraysContains(GenConstants.COLUMNTYPE_TEXT, dataType) ? GenConstants.HTML_TEXTAREA : GenConstants.HTML_INPUT; | |
| 48 | - column.setHtmlType(htmlType); | |
| 49 | - } else if (arraysContains(GenConstants.COLUMNTYPE_TIME, dataType)) { | |
| 50 | - column.setJavaType(GenConstants.TYPE_DATE); | |
| 51 | - column.setHtmlType(GenConstants.HTML_DATETIME); | |
| 52 | - } else if (arraysContains(GenConstants.COLUMNTYPE_NUMBER, dataType)) { | |
| 53 | - column.setHtmlType(GenConstants.HTML_INPUT); | |
| 54 | - | |
| 55 | - // 如果是浮点型 统一用BigDecimal | |
| 56 | - String[] str = StringUtils.split(StringUtils.substringBetween(column.getColumnType(), "(", ")"), ","); | |
| 57 | - if (str != null && str.length == 2 && Integer.parseInt(str[1]) > 0) { | |
| 58 | - column.setJavaType(GenConstants.TYPE_BIGDECIMAL); | |
| 59 | - } | |
| 60 | - // 如果是整形 | |
| 61 | - else if (str != null && str.length == 1 && Integer.parseInt(str[0]) <= 10) { | |
| 62 | - column.setJavaType(GenConstants.TYPE_INTEGER); | |
| 63 | - } | |
| 64 | - // 长整形 | |
| 65 | - else { | |
| 66 | - column.setJavaType(GenConstants.TYPE_LONG); | |
| 67 | - } | |
| 68 | - } | |
| 69 | - | |
| 70 | - // 插入字段(默认所有字段都需要插入) | |
| 71 | - column.setIsInsert(GenConstants.REQUIRE); | |
| 72 | - | |
| 73 | - // 编辑字段 | |
| 74 | - if (!arraysContains(GenConstants.COLUMNNAME_NOT_EDIT, columnName) && !column.isPk()) { | |
| 75 | - column.setIsEdit(GenConstants.REQUIRE); | |
| 76 | - } | |
| 77 | - // 列表字段 | |
| 78 | - if (!arraysContains(GenConstants.COLUMNNAME_NOT_LIST, columnName) && !column.isPk()) { | |
| 79 | - column.setIsList(GenConstants.REQUIRE); | |
| 80 | - } | |
| 81 | - // 查询字段 | |
| 82 | - if (!arraysContains(GenConstants.COLUMNNAME_NOT_QUERY, columnName) && !column.isPk()) { | |
| 83 | - column.setIsQuery(GenConstants.REQUIRE); | |
| 84 | - } | |
| 85 | - | |
| 86 | - // 查询字段类型 | |
| 87 | - if (StringUtils.endsWithIgnoreCase(columnName, "name")) { | |
| 88 | - column.setQueryType(GenConstants.QUERY_LIKE); | |
| 89 | - } | |
| 90 | - // 状态字段设置单选框 | |
| 91 | - if (StringUtils.endsWithIgnoreCase(columnName, "status")) { | |
| 92 | - column.setHtmlType(GenConstants.HTML_RADIO); | |
| 93 | - } | |
| 94 | - // 类型&性别字段设置下拉框 | |
| 95 | - else if (StringUtils.endsWithIgnoreCase(columnName, "type") | |
| 96 | - || StringUtils.endsWithIgnoreCase(columnName, "sex")) { | |
| 97 | - column.setHtmlType(GenConstants.HTML_SELECT); | |
| 98 | - } | |
| 99 | - // 文件字段设置上传控件 | |
| 100 | - else if (StringUtils.endsWithIgnoreCase(columnName, "image")) { | |
| 101 | - column.setHtmlType(GenConstants.HTML_UPLOAD_IMAGE); | |
| 102 | - } | |
| 103 | - // 内容字段设置富文本控件 | |
| 104 | - else if (StringUtils.endsWithIgnoreCase(columnName, "content")) { | |
| 105 | - column.setHtmlType(GenConstants.HTML_EDITOR); | |
| 106 | - } | |
| 107 | - } | |
| 108 | - | |
| 109 | - /** | |
| 110 | - * 校验数组是否包含指定值 | |
| 111 | - * | |
| 112 | - * @param arr 数组 | |
| 113 | - * @param targetValue 值 | |
| 114 | - * @return 是否包含 | |
| 115 | - */ | |
| 116 | - public static boolean arraysContains(String[] arr, String targetValue) { | |
| 117 | - return Arrays.asList(arr).contains(targetValue); | |
| 118 | - } | |
| 119 | - | |
| 120 | - /** | |
| 121 | - * 获取模块名 | |
| 122 | - * | |
| 123 | - * @param packageName 包名 | |
| 124 | - * @return 模块名 | |
| 125 | - */ | |
| 126 | - public static String getModuleName(String packageName) { | |
| 127 | - int lastIndex = packageName.lastIndexOf("."); | |
| 128 | - int nameLength = packageName.length(); | |
| 129 | - String moduleName = StringUtils.substring(packageName, lastIndex + 1, nameLength); | |
| 130 | - return moduleName; | |
| 131 | - } | |
| 132 | - | |
| 133 | - /** | |
| 134 | - * 获取业务名 | |
| 135 | - * | |
| 136 | - * @param tableName 表名 | |
| 137 | - * @return 业务名 | |
| 138 | - */ | |
| 139 | - public static String getBusinessName(String tableName) { | |
| 140 | - int lastIndex = tableName.lastIndexOf("_"); | |
| 141 | - int nameLength = tableName.length(); | |
| 142 | - String businessName = StringUtils.substring(tableName, lastIndex + 1, nameLength); | |
| 143 | - return businessName; | |
| 144 | - } | |
| 145 | - | |
| 146 | - /** | |
| 147 | - * 表名转换成Java类名 | |
| 148 | - * | |
| 149 | - * @param tableName 表名称 | |
| 150 | - * @return 类名 | |
| 151 | - */ | |
| 152 | - public static String convertClassName(String tableName) { | |
| 153 | - boolean autoRemovePre = GenConfig.getAutoRemovePre(); | |
| 154 | - String tablePrefix = GenConfig.getTablePrefix(); | |
| 155 | - if (autoRemovePre && StringUtils.isNotEmpty(tablePrefix)) { | |
| 156 | - String[] searchList = StringUtils.split(tablePrefix, ","); | |
| 157 | - tableName = replaceFirst(tableName, searchList); | |
| 158 | - } | |
| 159 | - return StringUtils.convertToCamelCase(tableName); | |
| 160 | - } | |
| 161 | - | |
| 162 | - /** | |
| 163 | - * 批量替换前缀 | |
| 164 | - * | |
| 165 | - * @param replacementm 替换值 | |
| 166 | - * @param searchList 替换列表 | |
| 167 | - * @return | |
| 168 | - */ | |
| 169 | - public static String replaceFirst(String replacementm, String[] searchList) { | |
| 170 | - String text = replacementm; | |
| 171 | - for (String searchString : searchList) { | |
| 172 | - if (replacementm.startsWith(searchString)) { | |
| 173 | - text = replacementm.replaceFirst(searchString, ""); | |
| 174 | - break; | |
| 175 | - } | |
| 176 | - } | |
| 177 | - return text; | |
| 178 | - } | |
| 179 | - | |
| 180 | - /** | |
| 181 | - * 关键字替换 | |
| 182 | - * | |
| 183 | - * @param text 需要被替换的名字 | |
| 184 | - * @return 替换后的名字 | |
| 185 | - */ | |
| 186 | - public static String replaceText(String text) { | |
| 187 | - return RegExUtils.replaceAll(text, "(?:表|若依)", ""); | |
| 188 | - } | |
| 189 | - | |
| 190 | - /** | |
| 191 | - * 获取数据库类型字段 | |
| 192 | - * | |
| 193 | - * @param columnType 列类型 | |
| 194 | - * @return 截取后的列类型 | |
| 195 | - */ | |
| 196 | - public static String getDbType(String columnType) { | |
| 197 | - if (StringUtils.indexOf(columnType, "(") > 0) { | |
| 198 | - return StringUtils.substringBefore(columnType, "("); | |
| 199 | - } else { | |
| 200 | - return columnType; | |
| 201 | - } | |
| 202 | - } | |
| 203 | - | |
| 204 | - /** | |
| 205 | - * 获取字段长度 | |
| 206 | - * | |
| 207 | - * @param columnType 列类型 | |
| 208 | - * @return 截取后的列类型 | |
| 209 | - */ | |
| 210 | - public static Integer getColumnLength(String columnType) { | |
| 211 | - if (StringUtils.indexOf(columnType, "(") > 0) { | |
| 212 | - String length = StringUtils.substringBetween(columnType, "(", ")"); | |
| 213 | - return Integer.valueOf(length); | |
| 214 | - } else { | |
| 215 | - return 0; | |
| 216 | - } | |
| 217 | - } | |
| 218 | -} |
src/main/java/cn/iocoder/dashboard/modules/tool/controller/codegen/ToolCodeGenController.java
| ... | ... | @@ -3,19 +3,31 @@ package cn.iocoder.dashboard.modules.tool.controller.codegen; |
| 3 | 3 | import cn.iocoder.dashboard.common.pojo.CommonResult; |
| 4 | 4 | import cn.iocoder.dashboard.common.pojo.PageResult; |
| 5 | 5 | import cn.iocoder.dashboard.modules.tool.controller.codegen.vo.ToolCodeGenTablePageItemRespVO; |
| 6 | -import org.springframework.web.bind.annotation.GetMapping; | |
| 7 | -import org.springframework.web.bind.annotation.RequestMapping; | |
| 8 | -import org.springframework.web.bind.annotation.RestController; | |
| 6 | +import cn.iocoder.dashboard.modules.tool.service.codegen.ToolCodegenService; | |
| 7 | +import io.swagger.annotations.ApiOperation; | |
| 8 | +import org.springframework.web.bind.annotation.*; | |
| 9 | + | |
| 10 | +import javax.annotation.Resource; | |
| 9 | 11 | |
| 10 | 12 | import static cn.iocoder.dashboard.common.pojo.CommonResult.success; |
| 11 | 13 | |
| 12 | 14 | @RestController |
| 13 | -@RequestMapping("/tool/code-gen") | |
| 15 | +@RequestMapping("/tool/codegen") | |
| 14 | 16 | public class ToolCodeGenController { |
| 15 | 17 | |
| 18 | + @Resource | |
| 19 | + private ToolCodegenService codegenService; | |
| 20 | + | |
| 16 | 21 | @GetMapping("/table/page") |
| 17 | 22 | public CommonResult<PageResult<ToolCodeGenTablePageItemRespVO>> getCodeGenTablePage() { |
| 18 | 23 | return success(null); |
| 19 | 24 | } |
| 20 | 25 | |
| 26 | + @ApiOperation("基于数据库的表结构,创建代码生成器的表定义") | |
| 27 | + @PostMapping("/table/create") | |
| 28 | + // TODO 权限 | |
| 29 | + public CommonResult<Long> createCodeGenTable(@RequestParam("tableName") String tableName) { | |
| 30 | + return success(codegenService.createCodegenTable(tableName)); | |
| 31 | + } | |
| 32 | + | |
| 21 | 33 | } | ... | ... |
src/main/java/cn/iocoder/dashboard/modules/tool/convert/codegen/CodegenConvert.java
0 → 100644
| 1 | +package cn.iocoder.dashboard.modules.tool.convert.codegen; | |
| 2 | + | |
| 3 | +import cn.iocoder.dashboard.modules.tool.dal.mysql.dataobject.codegen.ToolCodegenColumnDO; | |
| 4 | +import cn.iocoder.dashboard.modules.tool.dal.mysql.dataobject.codegen.ToolCodegenTableDO; | |
| 5 | +import cn.iocoder.dashboard.modules.tool.dal.mysql.dataobject.codegen.ToolInformationSchemaColumnDO; | |
| 6 | +import cn.iocoder.dashboard.modules.tool.dal.mysql.dataobject.codegen.ToolInformationSchemaTableDO; | |
| 7 | +import org.mapstruct.Mapper; | |
| 8 | +import org.mapstruct.factory.Mappers; | |
| 9 | + | |
| 10 | +import java.util.List; | |
| 11 | + | |
| 12 | +@Mapper | |
| 13 | +public interface CodegenConvert { | |
| 14 | + | |
| 15 | + CodegenConvert INSTANCE = Mappers.getMapper(CodegenConvert.class); | |
| 16 | + | |
| 17 | + ToolCodegenTableDO convert(ToolInformationSchemaTableDO bean); | |
| 18 | + | |
| 19 | + List<ToolCodegenColumnDO> convertList(List<ToolInformationSchemaColumnDO> list); | |
| 20 | + | |
| 21 | +} | ... | ... |
src/main/java/cn/iocoder/dashboard/modules/tool/convert/package-info.java
0 → 100644
| 1 | +package cn.iocoder.dashboard.modules.tool.convert; | ... | ... |
src/main/java/cn/iocoder/dashboard/modules/tool/dal/mysql/dao/coegen/ToolCodegenColumnMapper.java
0 → 100644
| 1 | +package cn.iocoder.dashboard.modules.tool.dal.mysql.dao.coegen; | |
| 2 | + | |
| 3 | +import cn.iocoder.dashboard.framework.mybatis.core.mapper.BaseMapperX; | |
| 4 | +import cn.iocoder.dashboard.modules.tool.dal.mysql.dataobject.codegen.ToolCodegenColumnDO; | |
| 5 | +import org.apache.ibatis.annotations.Mapper; | |
| 6 | + | |
| 7 | +@Mapper | |
| 8 | +public interface ToolCodegenColumnMapper extends BaseMapperX<ToolCodegenColumnDO> { | |
| 9 | +} | ... | ... |
src/main/java/cn/iocoder/dashboard/modules/tool/dal/mysql/dao/coegen/ToolCodegenTableMapper.java
0 → 100644
| 1 | +package cn.iocoder.dashboard.modules.tool.dal.mysql.dao.coegen; | |
| 2 | + | |
| 3 | +import cn.iocoder.dashboard.framework.mybatis.core.mapper.BaseMapperX; | |
| 4 | +import cn.iocoder.dashboard.modules.tool.dal.mysql.dataobject.codegen.ToolCodegenTableDO; | |
| 5 | +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; | |
| 6 | +import org.apache.ibatis.annotations.Mapper; | |
| 7 | + | |
| 8 | +@Mapper | |
| 9 | +public interface ToolCodegenTableMapper extends BaseMapperX<ToolCodegenTableDO> { | |
| 10 | + | |
| 11 | + default ToolCodegenTableDO selectByTableName(String tableName) { | |
| 12 | + return selectOne(new QueryWrapper<ToolCodegenTableDO>().eq("table_name", tableName)); | |
| 13 | + } | |
| 14 | + | |
| 15 | +} | ... | ... |
src/main/java/cn/iocoder/dashboard/modules/tool/dal/mysql/dao/coegen/ToolInformationSchemaTableMapper.java
| ... | ... | @@ -14,4 +14,8 @@ public interface ToolInformationSchemaTableMapper extends BaseMapperX<ToolInform |
| 14 | 14 | return selectList(new QueryWrapper<ToolInformationSchemaTableDO>().eq("table_schema", tableSchema)); |
| 15 | 15 | } |
| 16 | 16 | |
| 17 | + default ToolInformationSchemaTableDO selectByTableName(String tableName) { | |
| 18 | + return selectOne(new QueryWrapper<ToolInformationSchemaTableDO>().eq("table_name", tableName)); | |
| 19 | + } | |
| 20 | + | |
| 17 | 21 | } | ... | ... |
src/main/java/cn/iocoder/dashboard/modules/tool/enums/codegen/ToolCodegenColumnHtmlTypeEnum.java
| ... | ... | @@ -16,13 +16,14 @@ public enum ToolCodegenColumnHtmlTypeEnum { |
| 16 | 16 | RADIO("radio"), // 单选框 |
| 17 | 17 | CHECKBOX("checkbox"), // 复选框 |
| 18 | 18 | DATETIME("datetime"), // 日期控件 |
| 19 | - UPLOAD_IMAGE("upload_image"), // 上传控件 | |
| 19 | + UPLOAD_IMAGE("upload_image"), // 上传图片 | |
| 20 | + UPLOAD_FILE("upload_file"), // 上传文件 | |
| 20 | 21 | EDITOR("editor"), // 富文本控件 |
| 21 | 22 | ; |
| 22 | 23 | |
| 23 | 24 | /** |
| 24 | 25 | * 条件 |
| 25 | 26 | */ |
| 26 | - private final String condition; | |
| 27 | + private final String type; | |
| 27 | 28 | |
| 28 | 29 | } | ... | ... |
src/main/java/cn/iocoder/dashboard/modules/tool/service/codegen/ToolCodegenService.java
0 → 100644
| 1 | +package cn.iocoder.dashboard.modules.tool.service.codegen; | |
| 2 | + | |
| 3 | +/** | |
| 4 | + * 代码生成 Service 接口 | |
| 5 | + * | |
| 6 | + * @author 芋道源码 | |
| 7 | + */ | |
| 8 | +public interface ToolCodegenService { | |
| 9 | + | |
| 10 | + /** | |
| 11 | + * 基于数据库的表结构,创建代码生成器的表定义 | |
| 12 | + * | |
| 13 | + * @param tableName 表名称 | |
| 14 | + * @return 表定义的编号 | |
| 15 | + */ | |
| 16 | + Long createCodegenTable(String tableName); | |
| 17 | + | |
| 18 | +} | ... | ... |
src/main/java/cn/iocoder/dashboard/modules/tool/service/codegen/impl/ToolCodegenServiceImpl.java
0 → 100644
| 1 | +package cn.iocoder.dashboard.modules.tool.service.codegen.impl; | |
| 2 | + | |
| 3 | +import cn.hutool.core.collection.CollUtil; | |
| 4 | +import cn.hutool.core.map.MapUtil; | |
| 5 | +import cn.hutool.core.util.StrUtil; | |
| 6 | +import cn.iocoder.dashboard.framework.mybatis.core.dataobject.BaseDO; | |
| 7 | +import cn.iocoder.dashboard.modules.tool.convert.codegen.CodegenConvert; | |
| 8 | +import cn.iocoder.dashboard.modules.tool.dal.mysql.dao.coegen.ToolCodegenColumnMapper; | |
| 9 | +import cn.iocoder.dashboard.modules.tool.dal.mysql.dao.coegen.ToolCodegenTableMapper; | |
| 10 | +import cn.iocoder.dashboard.modules.tool.dal.mysql.dao.coegen.ToolInformationSchemaColumnMapper; | |
| 11 | +import cn.iocoder.dashboard.modules.tool.dal.mysql.dao.coegen.ToolInformationSchemaTableMapper; | |
| 12 | +import cn.iocoder.dashboard.modules.tool.dal.mysql.dataobject.codegen.ToolCodegenColumnDO; | |
| 13 | +import cn.iocoder.dashboard.modules.tool.dal.mysql.dataobject.codegen.ToolCodegenTableDO; | |
| 14 | +import cn.iocoder.dashboard.modules.tool.dal.mysql.dataobject.codegen.ToolInformationSchemaColumnDO; | |
| 15 | +import cn.iocoder.dashboard.modules.tool.dal.mysql.dataobject.codegen.ToolInformationSchemaTableDO; | |
| 16 | +import cn.iocoder.dashboard.modules.tool.enums.codegen.ToolCodegenColumnHtmlTypeEnum; | |
| 17 | +import cn.iocoder.dashboard.modules.tool.enums.codegen.ToolCodegenColumnListConditionEnum; | |
| 18 | +import cn.iocoder.dashboard.modules.tool.service.codegen.ToolCodegenService; | |
| 19 | +import com.google.common.collect.Sets; | |
| 20 | +import org.springframework.stereotype.Service; | |
| 21 | +import org.springframework.transaction.annotation.Transactional; | |
| 22 | + | |
| 23 | +import javax.annotation.Resource; | |
| 24 | +import java.math.BigDecimal; | |
| 25 | +import java.util.*; | |
| 26 | + | |
| 27 | +/** | |
| 28 | + * 代码生成 Service 实现类 | |
| 29 | + * | |
| 30 | + * @author 芋道源码 | |
| 31 | + */ | |
| 32 | +@Service | |
| 33 | +public class ToolCodegenServiceImpl implements ToolCodegenService { | |
| 34 | + | |
| 35 | + /** | |
| 36 | + * 字段名与 {@link ToolCodegenColumnListConditionEnum} 的默认映射 | |
| 37 | + * 注意,字段的匹配以后缀的方式 | |
| 38 | + */ | |
| 39 | + private static final Map<String, ToolCodegenColumnListConditionEnum> columnListOperationConditionMappings = | |
| 40 | + MapUtil.<String, ToolCodegenColumnListConditionEnum>builder() | |
| 41 | + .put("name", ToolCodegenColumnListConditionEnum.LIKE) | |
| 42 | + .put("time", ToolCodegenColumnListConditionEnum.BETWEEN) | |
| 43 | + .put("date", ToolCodegenColumnListConditionEnum.BETWEEN) | |
| 44 | + .build(); | |
| 45 | + | |
| 46 | + /** | |
| 47 | + * 字段名与 {@link ToolCodegenColumnHtmlTypeEnum} 的默认映射 | |
| 48 | + * 注意,字段的匹配以后缀的方式 | |
| 49 | + */ | |
| 50 | + private static final Map<String, ToolCodegenColumnHtmlTypeEnum> columnHtmlTypeMappings = | |
| 51 | + MapUtil.<String, ToolCodegenColumnHtmlTypeEnum>builder() | |
| 52 | + .put("status", ToolCodegenColumnHtmlTypeEnum.RADIO) | |
| 53 | + .put("sex", ToolCodegenColumnHtmlTypeEnum.RADIO) | |
| 54 | + .put("type", ToolCodegenColumnHtmlTypeEnum.SELECT) | |
| 55 | + .put("image", ToolCodegenColumnHtmlTypeEnum.UPLOAD_IMAGE) | |
| 56 | + .put("file", ToolCodegenColumnHtmlTypeEnum.UPLOAD_FILE) | |
| 57 | + .put("content", ToolCodegenColumnHtmlTypeEnum.EDITOR) | |
| 58 | + .build(); | |
| 59 | + | |
| 60 | + /** | |
| 61 | + * 新增操作,不需要传递的字段 | |
| 62 | + */ | |
| 63 | + private static final Set<String> CREATE_OPERATION_EXCLUDE_COLUMN = Sets.newHashSet( | |
| 64 | + "id"); | |
| 65 | + /** | |
| 66 | + * 修改操作,不需要传递的字段 | |
| 67 | + */ | |
| 68 | + private static final Set<String> UPDATE_OPERATION_EXCLUDE_COLUMN = Sets.newHashSet(); | |
| 69 | + /** | |
| 70 | + * 列表操作的条件,不需要传递的字段 | |
| 71 | + */ | |
| 72 | + private static final Set<String> LIST_OPERATION_CONDITION_COLUMN = Sets.newHashSet(); | |
| 73 | + /** | |
| 74 | + * 列表操作的结果,不需要返回的字段 | |
| 75 | + */ | |
| 76 | + private static final Set<String> LIST_OPERATION_RESULT_COLUMN = Sets.newHashSet(); | |
| 77 | + | |
| 78 | + /** | |
| 79 | + * Java 类型与 MySQL 类型的映射关系 | |
| 80 | + */ | |
| 81 | + private static final Map<String, Set<String>> javaTypeMappings = MapUtil.<String, Set<String>>builder() | |
| 82 | + .put(Boolean.class.getSimpleName(), Sets.newHashSet("bit")) | |
| 83 | + .put(Integer.class.getSimpleName(), Sets.newHashSet("tinyint", "smallint", "mediumint", "int")) | |
| 84 | + .put(Long.class.getSimpleName(), Collections.singleton("bigint")) | |
| 85 | + .put(Double.class.getSimpleName(), Sets.newHashSet("float", "double")) | |
| 86 | + .put(BigDecimal.class.getSimpleName(), Sets.newHashSet("decimal", "numeric")) | |
| 87 | + .put(String.class.getSimpleName(), Sets.newHashSet("tinytext", "text", "mediumtext", "longtext", // 长文本 | |
| 88 | + "char", "varchar", "nvarchar", "varchar2")) // 短文本 | |
| 89 | + .put(Date.class.getSimpleName(), Sets.newHashSet("datetime", "time", "date", "timestamp")) | |
| 90 | + .build(); | |
| 91 | + | |
| 92 | + static { | |
| 93 | + Arrays.stream(BaseDO.class.getDeclaredFields()).forEach(field -> { | |
| 94 | + CREATE_OPERATION_EXCLUDE_COLUMN.add(field.getName()); | |
| 95 | + UPDATE_OPERATION_EXCLUDE_COLUMN.add(field.getName()); | |
| 96 | + LIST_OPERATION_CONDITION_COLUMN.add(field.getName()); | |
| 97 | + LIST_OPERATION_RESULT_COLUMN.add(field.getName()); | |
| 98 | + }); | |
| 99 | + LIST_OPERATION_RESULT_COLUMN.remove("create_time"); // 创建时间,还是需要返回的 | |
| 100 | + } | |
| 101 | + | |
| 102 | + @Resource | |
| 103 | + private ToolInformationSchemaTableMapper informationSchemaTableMapper; | |
| 104 | + @Resource | |
| 105 | + private ToolInformationSchemaColumnMapper informationSchemaColumnMapper; | |
| 106 | + @Resource | |
| 107 | + private ToolCodegenTableMapper codegenTableMapper; | |
| 108 | + @Resource | |
| 109 | + private ToolCodegenColumnMapper codegenColumnMapper; | |
| 110 | + | |
| 111 | + @Override | |
| 112 | + @Transactional | |
| 113 | + public Long createCodegenTable(String tableName) { | |
| 114 | + // 从数据库中,获得数据库表结构 | |
| 115 | + ToolInformationSchemaTableDO schemaTable = informationSchemaTableMapper.selectByTableName(tableName); | |
| 116 | + if (schemaTable == null) { | |
| 117 | + throw new RuntimeException(""); // TODO | |
| 118 | + } | |
| 119 | + List<ToolInformationSchemaColumnDO> schemaColumns = informationSchemaColumnMapper.selectListByTableName(tableName); | |
| 120 | + if (CollUtil.isEmpty(schemaColumns)) { | |
| 121 | + throw new RuntimeException(""); // TODO | |
| 122 | + } | |
| 123 | + // 校验是否已经存在 | |
| 124 | + if (codegenTableMapper.selectByTableName(tableName) != null) { | |
| 125 | + throw new RuntimeException(""); // TODO | |
| 126 | + } | |
| 127 | + | |
| 128 | + // 将 table 插入到数据库 | |
| 129 | + ToolCodegenTableDO table = CodegenConvert.INSTANCE.convert(schemaTable); | |
| 130 | + initTableDefault(table); | |
| 131 | + codegenTableMapper.insert(table); | |
| 132 | + // 将 column 插入到数据库 | |
| 133 | + List<ToolCodegenColumnDO> columns = CodegenConvert.INSTANCE.convertList(schemaColumns); | |
| 134 | + columns.forEach(column -> { | |
| 135 | + initColumnDefault(column); | |
| 136 | + column.setTableId(table.getId()); | |
| 137 | + codegenColumnMapper.insert(column); | |
| 138 | + }); | |
| 139 | + return table.getId(); | |
| 140 | + } | |
| 141 | + | |
| 142 | + /** | |
| 143 | + * 初始化 Table 表的默认字段 | |
| 144 | + * | |
| 145 | + * @param table 表定义 | |
| 146 | + */ | |
| 147 | + private void initTableDefault(ToolCodegenTableDO table) { | |
| 148 | + table.setModuleName(StrUtil.subBefore(table.getTableName(), | |
| 149 | + '_', false)); // 第一个 _ 前缀的前面,作为 module 名字 | |
| 150 | + table.setBusinessName(StrUtil.subAfter(table.getTableName(), | |
| 151 | + '_', false)); // 第一个 _ 前缀的后面,作为 module 名字 | |
| 152 | + table.setBusinessName(StrUtil.toCamelCase(table.getBusinessName())); // 可能存在多个 _ 的情况,转换成驼峰 | |
| 153 | + table.setClassName(StrUtil.toCamelCase(table.getClassName())); // 驼峰 | |
| 154 | + table.setClassComment(StrUtil.subBefore(table.getClassComment(), // 去除结尾的表,作为类描述 | |
| 155 | + '表', true)); | |
| 156 | + table.setAuthor("芋艿"); // TODO 稍后改成创建人 | |
| 157 | + } | |
| 158 | + | |
| 159 | + /** | |
| 160 | + * 初始化 Column 列的默认字段 | |
| 161 | + * | |
| 162 | + * @param column 列定义 | |
| 163 | + */ | |
| 164 | + private void initColumnDefault(ToolCodegenColumnDO column) { | |
| 165 | + // 处理 Java 相关的字段的默认值 | |
| 166 | + processColumnJava(column); | |
| 167 | + // 处理 CRUD 相关的字段的默认值 | |
| 168 | + processColumnOperation(column); | |
| 169 | + // 处理 UI 相关的字段的默认值 | |
| 170 | + processColumnUI(column); | |
| 171 | + } | |
| 172 | + | |
| 173 | + private void processColumnJava(ToolCodegenColumnDO column) { | |
| 174 | + // 处理 javaField 字段 | |
| 175 | + column.setJavaField(StrUtil.toCamelCase(column.getColumnName())); | |
| 176 | + // 处理 dictType 字段,暂无 | |
| 177 | + // 处理 javaType 字段 | |
| 178 | + String dbType = StrUtil.subBefore(column.getColumnName(), ')', false); | |
| 179 | + javaTypeMappings.entrySet().stream() | |
| 180 | + .filter(entry -> entry.getValue().contains(dbType)) | |
| 181 | + .findFirst().ifPresent(entry -> column.setJavaType(entry.getKey())); | |
| 182 | + if (column.getJavaType() == null) { | |
| 183 | + throw new IllegalStateException(String.format("column(%s) 的数据库类型(%s) 找不到匹配的 Java 类型", | |
| 184 | + column.getColumnName(), column.getColumnType())); | |
| 185 | + } | |
| 186 | + } | |
| 187 | + | |
| 188 | + private void processColumnOperation(ToolCodegenColumnDO column) { | |
| 189 | + // 处理 createOperation 字段 | |
| 190 | + column.setCreateOperation(!CREATE_OPERATION_EXCLUDE_COLUMN.contains(column.getColumnName()) | |
| 191 | + && !column.getPrimaryKey()); // 非主键 | |
| 192 | + // 处理 updateOperation 字段 | |
| 193 | + column.setUpdateOperation(!UPDATE_OPERATION_EXCLUDE_COLUMN.contains(column.getColumnName())); | |
| 194 | + // 处理 listOperationResult 字段 | |
| 195 | + column.setListOperationResult(!LIST_OPERATION_RESULT_COLUMN.contains(column.getColumnName())); | |
| 196 | + // 处理 listOperationCondition 字段。默认设置为需要过滤的条件,手动进行取消 | |
| 197 | + if (!LIST_OPERATION_CONDITION_COLUMN.contains(column.getColumnName()) | |
| 198 | + && !column.getPrimaryKey()) { // 非主键 | |
| 199 | + column.setListOperationCondition(ToolCodegenColumnListConditionEnum.EQ.getCondition()); | |
| 200 | + } | |
| 201 | + columnListOperationConditionMappings.entrySet().stream() | |
| 202 | + .filter(entry -> StrUtil.endWithIgnoreCase(column.getColumnName(), entry.getKey())) | |
| 203 | + .findFirst().ifPresent(entry -> column.setListOperationCondition(entry.getValue().getCondition())); | |
| 204 | + } | |
| 205 | + | |
| 206 | + private void processColumnUI(ToolCodegenColumnDO column) { | |
| 207 | + // 基于后缀进行匹配 | |
| 208 | + columnHtmlTypeMappings.entrySet().stream() | |
| 209 | + .filter(entry -> StrUtil.endWithIgnoreCase(column.getColumnName(), entry.getKey())) | |
| 210 | + .findFirst().ifPresent(entry -> column.setHtmlType(entry.getValue().getType())); | |
| 211 | + // 如果是 Boolean 类型时,设置为 radio 类型. | |
| 212 | + // 其它类型,因为字段名可以相对保障,所以不进行处理。例如说 date 对应 datetime 类型. | |
| 213 | + if (Boolean.class.getSimpleName().equals(column.getJavaType())) { | |
| 214 | + column.setHtmlType(ToolCodegenColumnHtmlTypeEnum.RADIO.getType()); | |
| 215 | + } | |
| 216 | + // 兜底,设置默认为 input 类型 | |
| 217 | + if (column.getHtmlType() == null) { | |
| 218 | + column.setHtmlType(ToolCodegenColumnHtmlTypeEnum.INPUT.getType()); | |
| 219 | + } | |
| 220 | + } | |
| 221 | + | |
| 222 | +} | ... | ... |
src/main/java/cn/iocoder/dashboard/modules/tool/service/package-info.java
0 → 100644
| 1 | +package cn.iocoder.dashboard.modules.tool.service; | ... | ... |