mirror of
				https://gitee.com/hhyykk/ipms-sjy.git
				synced 2025-10-31 10:18:42 +08:00 
			
		
		
		
	实现数据库字段的解析
This commit is contained in:
		| @@ -3,19 +3,31 @@ package cn.iocoder.dashboard.modules.tool.controller.codegen; | ||||
| import cn.iocoder.dashboard.common.pojo.CommonResult; | ||||
| import cn.iocoder.dashboard.common.pojo.PageResult; | ||||
| import cn.iocoder.dashboard.modules.tool.controller.codegen.vo.ToolCodeGenTablePageItemRespVO; | ||||
| import org.springframework.web.bind.annotation.GetMapping; | ||||
| import org.springframework.web.bind.annotation.RequestMapping; | ||||
| import org.springframework.web.bind.annotation.RestController; | ||||
| import cn.iocoder.dashboard.modules.tool.service.codegen.ToolCodegenService; | ||||
| import io.swagger.annotations.ApiOperation; | ||||
| import org.springframework.web.bind.annotation.*; | ||||
|  | ||||
| import javax.annotation.Resource; | ||||
|  | ||||
| import static cn.iocoder.dashboard.common.pojo.CommonResult.success; | ||||
|  | ||||
| @RestController | ||||
| @RequestMapping("/tool/code-gen") | ||||
| @RequestMapping("/tool/codegen") | ||||
| public class ToolCodeGenController { | ||||
|  | ||||
|     @Resource | ||||
|     private ToolCodegenService codegenService; | ||||
|  | ||||
|     @GetMapping("/table/page") | ||||
|     public CommonResult<PageResult<ToolCodeGenTablePageItemRespVO>> getCodeGenTablePage() { | ||||
|         return success(null); | ||||
|     } | ||||
|  | ||||
|     @ApiOperation("基于数据库的表结构,创建代码生成器的表定义") | ||||
|     @PostMapping("/table/create") | ||||
|     // TODO 权限 | ||||
|     public CommonResult<Long> createCodeGenTable(@RequestParam("tableName") String tableName) { | ||||
|         return success(codegenService.createCodegenTable(tableName)); | ||||
|     } | ||||
|  | ||||
| } | ||||
|   | ||||
| @@ -0,0 +1,21 @@ | ||||
| package cn.iocoder.dashboard.modules.tool.convert.codegen; | ||||
|  | ||||
| import cn.iocoder.dashboard.modules.tool.dal.mysql.dataobject.codegen.ToolCodegenColumnDO; | ||||
| import cn.iocoder.dashboard.modules.tool.dal.mysql.dataobject.codegen.ToolCodegenTableDO; | ||||
| import cn.iocoder.dashboard.modules.tool.dal.mysql.dataobject.codegen.ToolInformationSchemaColumnDO; | ||||
| import cn.iocoder.dashboard.modules.tool.dal.mysql.dataobject.codegen.ToolInformationSchemaTableDO; | ||||
| import org.mapstruct.Mapper; | ||||
| import org.mapstruct.factory.Mappers; | ||||
|  | ||||
| import java.util.List; | ||||
|  | ||||
| @Mapper | ||||
| public interface CodegenConvert { | ||||
|  | ||||
|     CodegenConvert INSTANCE = Mappers.getMapper(CodegenConvert.class); | ||||
|  | ||||
|     ToolCodegenTableDO convert(ToolInformationSchemaTableDO bean); | ||||
|  | ||||
|     List<ToolCodegenColumnDO> convertList(List<ToolInformationSchemaColumnDO> list); | ||||
|  | ||||
| } | ||||
| @@ -0,0 +1 @@ | ||||
| package cn.iocoder.dashboard.modules.tool.convert; | ||||
| @@ -0,0 +1,9 @@ | ||||
| package cn.iocoder.dashboard.modules.tool.dal.mysql.dao.coegen; | ||||
|  | ||||
| import cn.iocoder.dashboard.framework.mybatis.core.mapper.BaseMapperX; | ||||
| import cn.iocoder.dashboard.modules.tool.dal.mysql.dataobject.codegen.ToolCodegenColumnDO; | ||||
| import org.apache.ibatis.annotations.Mapper; | ||||
|  | ||||
| @Mapper | ||||
| public interface ToolCodegenColumnMapper extends BaseMapperX<ToolCodegenColumnDO> { | ||||
| } | ||||
| @@ -0,0 +1,15 @@ | ||||
| package cn.iocoder.dashboard.modules.tool.dal.mysql.dao.coegen; | ||||
|  | ||||
| import cn.iocoder.dashboard.framework.mybatis.core.mapper.BaseMapperX; | ||||
| import cn.iocoder.dashboard.modules.tool.dal.mysql.dataobject.codegen.ToolCodegenTableDO; | ||||
| import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; | ||||
| import org.apache.ibatis.annotations.Mapper; | ||||
|  | ||||
| @Mapper | ||||
| public interface ToolCodegenTableMapper extends BaseMapperX<ToolCodegenTableDO> { | ||||
|  | ||||
|     default ToolCodegenTableDO selectByTableName(String tableName) { | ||||
|         return selectOne(new QueryWrapper<ToolCodegenTableDO>().eq("table_name", tableName)); | ||||
|     } | ||||
|  | ||||
| } | ||||
| @@ -14,4 +14,8 @@ public interface ToolInformationSchemaTableMapper extends BaseMapperX<ToolInform | ||||
|         return selectList(new QueryWrapper<ToolInformationSchemaTableDO>().eq("table_schema", tableSchema)); | ||||
|     } | ||||
|  | ||||
|     default ToolInformationSchemaTableDO selectByTableName(String tableName) { | ||||
|         return selectOne(new QueryWrapper<ToolInformationSchemaTableDO>().eq("table_name", tableName)); | ||||
|     } | ||||
|  | ||||
| } | ||||
|   | ||||
| @@ -16,13 +16,14 @@ public enum ToolCodegenColumnHtmlTypeEnum { | ||||
|     RADIO("radio"), // 单选框 | ||||
|     CHECKBOX("checkbox"), // 复选框 | ||||
|     DATETIME("datetime"), // 日期控件 | ||||
|     UPLOAD_IMAGE("upload_image"), // 上传控件 | ||||
|     UPLOAD_IMAGE("upload_image"), // 上传图片 | ||||
|     UPLOAD_FILE("upload_file"), // 上传文件 | ||||
|     EDITOR("editor"), // 富文本控件 | ||||
|     ; | ||||
|  | ||||
|     /** | ||||
|      * 条件 | ||||
|      */ | ||||
|     private final String condition; | ||||
|     private final String type; | ||||
|  | ||||
| } | ||||
|   | ||||
| @@ -0,0 +1,18 @@ | ||||
| package cn.iocoder.dashboard.modules.tool.service.codegen; | ||||
|  | ||||
| /** | ||||
|  * 代码生成 Service 接口 | ||||
|  * | ||||
|  * @author 芋道源码 | ||||
|  */ | ||||
| public interface ToolCodegenService { | ||||
|  | ||||
|     /** | ||||
|      * 基于数据库的表结构,创建代码生成器的表定义 | ||||
|      * | ||||
|      * @param tableName 表名称 | ||||
|      * @return 表定义的编号 | ||||
|      */ | ||||
|     Long createCodegenTable(String tableName); | ||||
|  | ||||
| } | ||||
| @@ -0,0 +1,222 @@ | ||||
| package cn.iocoder.dashboard.modules.tool.service.codegen.impl; | ||||
|  | ||||
| import cn.hutool.core.collection.CollUtil; | ||||
| import cn.hutool.core.map.MapUtil; | ||||
| import cn.hutool.core.util.StrUtil; | ||||
| import cn.iocoder.dashboard.framework.mybatis.core.dataobject.BaseDO; | ||||
| import cn.iocoder.dashboard.modules.tool.convert.codegen.CodegenConvert; | ||||
| import cn.iocoder.dashboard.modules.tool.dal.mysql.dao.coegen.ToolCodegenColumnMapper; | ||||
| import cn.iocoder.dashboard.modules.tool.dal.mysql.dao.coegen.ToolCodegenTableMapper; | ||||
| import cn.iocoder.dashboard.modules.tool.dal.mysql.dao.coegen.ToolInformationSchemaColumnMapper; | ||||
| import cn.iocoder.dashboard.modules.tool.dal.mysql.dao.coegen.ToolInformationSchemaTableMapper; | ||||
| import cn.iocoder.dashboard.modules.tool.dal.mysql.dataobject.codegen.ToolCodegenColumnDO; | ||||
| import cn.iocoder.dashboard.modules.tool.dal.mysql.dataobject.codegen.ToolCodegenTableDO; | ||||
| import cn.iocoder.dashboard.modules.tool.dal.mysql.dataobject.codegen.ToolInformationSchemaColumnDO; | ||||
| import cn.iocoder.dashboard.modules.tool.dal.mysql.dataobject.codegen.ToolInformationSchemaTableDO; | ||||
| import cn.iocoder.dashboard.modules.tool.enums.codegen.ToolCodegenColumnHtmlTypeEnum; | ||||
| import cn.iocoder.dashboard.modules.tool.enums.codegen.ToolCodegenColumnListConditionEnum; | ||||
| import cn.iocoder.dashboard.modules.tool.service.codegen.ToolCodegenService; | ||||
| import com.google.common.collect.Sets; | ||||
| import org.springframework.stereotype.Service; | ||||
| import org.springframework.transaction.annotation.Transactional; | ||||
|  | ||||
| import javax.annotation.Resource; | ||||
| import java.math.BigDecimal; | ||||
| import java.util.*; | ||||
|  | ||||
| /** | ||||
|  * 代码生成 Service 实现类 | ||||
|  * | ||||
|  * @author 芋道源码 | ||||
|  */ | ||||
| @Service | ||||
| public class ToolCodegenServiceImpl implements ToolCodegenService { | ||||
|  | ||||
|     /** | ||||
|      * 字段名与 {@link ToolCodegenColumnListConditionEnum} 的默认映射 | ||||
|      * 注意,字段的匹配以后缀的方式 | ||||
|      */ | ||||
|     private static final Map<String, ToolCodegenColumnListConditionEnum> columnListOperationConditionMappings = | ||||
|             MapUtil.<String, ToolCodegenColumnListConditionEnum>builder() | ||||
|                     .put("name", ToolCodegenColumnListConditionEnum.LIKE) | ||||
|                     .put("time", ToolCodegenColumnListConditionEnum.BETWEEN) | ||||
|                     .put("date", ToolCodegenColumnListConditionEnum.BETWEEN) | ||||
|                     .build(); | ||||
|  | ||||
|     /** | ||||
|      * 字段名与 {@link ToolCodegenColumnHtmlTypeEnum} 的默认映射 | ||||
|      * 注意,字段的匹配以后缀的方式 | ||||
|      */ | ||||
|     private static final Map<String, ToolCodegenColumnHtmlTypeEnum> columnHtmlTypeMappings = | ||||
|             MapUtil.<String, ToolCodegenColumnHtmlTypeEnum>builder() | ||||
|                     .put("status", ToolCodegenColumnHtmlTypeEnum.RADIO) | ||||
|                     .put("sex", ToolCodegenColumnHtmlTypeEnum.RADIO) | ||||
|                     .put("type", ToolCodegenColumnHtmlTypeEnum.SELECT) | ||||
|                     .put("image", ToolCodegenColumnHtmlTypeEnum.UPLOAD_IMAGE) | ||||
|                     .put("file", ToolCodegenColumnHtmlTypeEnum.UPLOAD_FILE) | ||||
|                     .put("content", ToolCodegenColumnHtmlTypeEnum.EDITOR) | ||||
|                     .build(); | ||||
|  | ||||
|     /** | ||||
|      * 新增操作,不需要传递的字段 | ||||
|      */ | ||||
|     private static final Set<String> CREATE_OPERATION_EXCLUDE_COLUMN = Sets.newHashSet( | ||||
|             "id"); | ||||
|     /** | ||||
|      * 修改操作,不需要传递的字段 | ||||
|      */ | ||||
|     private static final Set<String> UPDATE_OPERATION_EXCLUDE_COLUMN = Sets.newHashSet(); | ||||
|     /** | ||||
|      * 列表操作的条件,不需要传递的字段 | ||||
|      */ | ||||
|     private static final Set<String> LIST_OPERATION_CONDITION_COLUMN = Sets.newHashSet(); | ||||
|     /** | ||||
|      * 列表操作的结果,不需要返回的字段 | ||||
|      */ | ||||
|     private static final Set<String> LIST_OPERATION_RESULT_COLUMN = Sets.newHashSet(); | ||||
|  | ||||
|     /** | ||||
|      * Java 类型与 MySQL 类型的映射关系 | ||||
|      */ | ||||
|     private static final Map<String, Set<String>> javaTypeMappings = MapUtil.<String, Set<String>>builder() | ||||
|             .put(Boolean.class.getSimpleName(), Sets.newHashSet("bit")) | ||||
|             .put(Integer.class.getSimpleName(), Sets.newHashSet("tinyint", "smallint", "mediumint", "int")) | ||||
|             .put(Long.class.getSimpleName(), Collections.singleton("bigint")) | ||||
|             .put(Double.class.getSimpleName(), Sets.newHashSet("float", "double")) | ||||
|             .put(BigDecimal.class.getSimpleName(), Sets.newHashSet("decimal", "numeric")) | ||||
|             .put(String.class.getSimpleName(), Sets.newHashSet("tinytext", "text", "mediumtext", "longtext", // 长文本 | ||||
|                     "char", "varchar", "nvarchar", "varchar2")) // 短文本 | ||||
|             .put(Date.class.getSimpleName(), Sets.newHashSet("datetime", "time", "date", "timestamp")) | ||||
|             .build(); | ||||
|  | ||||
|     static { | ||||
|         Arrays.stream(BaseDO.class.getDeclaredFields()).forEach(field -> { | ||||
|             CREATE_OPERATION_EXCLUDE_COLUMN.add(field.getName()); | ||||
|             UPDATE_OPERATION_EXCLUDE_COLUMN.add(field.getName()); | ||||
|             LIST_OPERATION_CONDITION_COLUMN.add(field.getName()); | ||||
|             LIST_OPERATION_RESULT_COLUMN.add(field.getName()); | ||||
|         }); | ||||
|         LIST_OPERATION_RESULT_COLUMN.remove("create_time"); // 创建时间,还是需要返回的 | ||||
|     } | ||||
|  | ||||
|     @Resource | ||||
|     private ToolInformationSchemaTableMapper informationSchemaTableMapper; | ||||
|     @Resource | ||||
|     private ToolInformationSchemaColumnMapper informationSchemaColumnMapper; | ||||
|     @Resource | ||||
|     private ToolCodegenTableMapper codegenTableMapper; | ||||
|     @Resource | ||||
|     private ToolCodegenColumnMapper codegenColumnMapper; | ||||
|  | ||||
|     @Override | ||||
|     @Transactional | ||||
|     public Long createCodegenTable(String tableName) { | ||||
|         // 从数据库中,获得数据库表结构 | ||||
|         ToolInformationSchemaTableDO schemaTable = informationSchemaTableMapper.selectByTableName(tableName); | ||||
|         if (schemaTable == null) { | ||||
|             throw new RuntimeException(""); // TODO | ||||
|         } | ||||
|         List<ToolInformationSchemaColumnDO> schemaColumns = informationSchemaColumnMapper.selectListByTableName(tableName); | ||||
|         if (CollUtil.isEmpty(schemaColumns)) { | ||||
|             throw new RuntimeException(""); // TODO | ||||
|         } | ||||
|         // 校验是否已经存在 | ||||
|         if (codegenTableMapper.selectByTableName(tableName) != null) { | ||||
|             throw new RuntimeException(""); // TODO | ||||
|         } | ||||
|  | ||||
|         // 将 table 插入到数据库 | ||||
|         ToolCodegenTableDO table = CodegenConvert.INSTANCE.convert(schemaTable); | ||||
|         initTableDefault(table); | ||||
|         codegenTableMapper.insert(table); | ||||
|         // 将 column 插入到数据库 | ||||
|         List<ToolCodegenColumnDO> columns = CodegenConvert.INSTANCE.convertList(schemaColumns); | ||||
|         columns.forEach(column -> { | ||||
|             initColumnDefault(column); | ||||
|             column.setTableId(table.getId()); | ||||
|             codegenColumnMapper.insert(column); | ||||
|         }); | ||||
|         return table.getId(); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 初始化 Table 表的默认字段 | ||||
|      * | ||||
|      * @param table 表定义 | ||||
|      */ | ||||
|     private void initTableDefault(ToolCodegenTableDO table) { | ||||
|         table.setModuleName(StrUtil.subBefore(table.getTableName(), | ||||
|                 '_', false)); // 第一个 _ 前缀的前面,作为 module 名字 | ||||
|         table.setBusinessName(StrUtil.subAfter(table.getTableName(), | ||||
|                 '_', false)); // 第一个 _ 前缀的后面,作为 module 名字 | ||||
|         table.setBusinessName(StrUtil.toCamelCase(table.getBusinessName())); // 可能存在多个 _ 的情况,转换成驼峰 | ||||
|         table.setClassName(StrUtil.toCamelCase(table.getClassName())); // 驼峰 | ||||
|         table.setClassComment(StrUtil.subBefore(table.getClassComment(), // 去除结尾的表,作为类描述 | ||||
|                 '表', true)); | ||||
|         table.setAuthor("芋艿"); // TODO 稍后改成创建人 | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 初始化 Column 列的默认字段 | ||||
|      * | ||||
|      * @param column 列定义 | ||||
|      */ | ||||
|     private void initColumnDefault(ToolCodegenColumnDO column) { | ||||
|         // 处理 Java 相关的字段的默认值 | ||||
|         processColumnJava(column); | ||||
|         // 处理 CRUD 相关的字段的默认值 | ||||
|         processColumnOperation(column); | ||||
|         // 处理 UI 相关的字段的默认值 | ||||
|         processColumnUI(column); | ||||
|     } | ||||
|  | ||||
|     private void processColumnJava(ToolCodegenColumnDO column) { | ||||
|         // 处理 javaField 字段 | ||||
|         column.setJavaField(StrUtil.toCamelCase(column.getColumnName())); | ||||
|         // 处理 dictType 字段,暂无 | ||||
|         // 处理 javaType 字段 | ||||
|         String dbType = StrUtil.subBefore(column.getColumnName(), ')', false); | ||||
|         javaTypeMappings.entrySet().stream() | ||||
|                 .filter(entry -> entry.getValue().contains(dbType)) | ||||
|                 .findFirst().ifPresent(entry -> column.setJavaType(entry.getKey())); | ||||
|         if (column.getJavaType() == null) { | ||||
|             throw new IllegalStateException(String.format("column(%s) 的数据库类型(%s) 找不到匹配的 Java 类型", | ||||
|                     column.getColumnName(), column.getColumnType())); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     private void processColumnOperation(ToolCodegenColumnDO column) { | ||||
|         // 处理 createOperation 字段 | ||||
|         column.setCreateOperation(!CREATE_OPERATION_EXCLUDE_COLUMN.contains(column.getColumnName()) | ||||
|             && !column.getPrimaryKey()); // 非主键 | ||||
|         // 处理 updateOperation 字段 | ||||
|         column.setUpdateOperation(!UPDATE_OPERATION_EXCLUDE_COLUMN.contains(column.getColumnName())); | ||||
|         // 处理 listOperationResult 字段 | ||||
|         column.setListOperationResult(!LIST_OPERATION_RESULT_COLUMN.contains(column.getColumnName())); | ||||
|         // 处理 listOperationCondition 字段。默认设置为需要过滤的条件,手动进行取消 | ||||
|         if (!LIST_OPERATION_CONDITION_COLUMN.contains(column.getColumnName()) | ||||
|             && !column.getPrimaryKey()) { // 非主键 | ||||
|             column.setListOperationCondition(ToolCodegenColumnListConditionEnum.EQ.getCondition()); | ||||
|         } | ||||
|         columnListOperationConditionMappings.entrySet().stream() | ||||
|                 .filter(entry -> StrUtil.endWithIgnoreCase(column.getColumnName(), entry.getKey())) | ||||
|                 .findFirst().ifPresent(entry -> column.setListOperationCondition(entry.getValue().getCondition())); | ||||
|     } | ||||
|  | ||||
|     private void processColumnUI(ToolCodegenColumnDO column) { | ||||
|         // 基于后缀进行匹配 | ||||
|         columnHtmlTypeMappings.entrySet().stream() | ||||
|                 .filter(entry -> StrUtil.endWithIgnoreCase(column.getColumnName(), entry.getKey())) | ||||
|                 .findFirst().ifPresent(entry -> column.setHtmlType(entry.getValue().getType())); | ||||
|         // 如果是 Boolean 类型时,设置为 radio 类型. | ||||
|         // 其它类型,因为字段名可以相对保障,所以不进行处理。例如说 date 对应 datetime 类型. | ||||
|         if (Boolean.class.getSimpleName().equals(column.getJavaType())) { | ||||
|             column.setHtmlType(ToolCodegenColumnHtmlTypeEnum.RADIO.getType()); | ||||
|         } | ||||
|         // 兜底,设置默认为 input 类型 | ||||
|         if (column.getHtmlType() == null) { | ||||
|             column.setHtmlType(ToolCodegenColumnHtmlTypeEnum.INPUT.getType()); | ||||
|         } | ||||
|     } | ||||
|  | ||||
| } | ||||
| @@ -0,0 +1 @@ | ||||
| package cn.iocoder.dashboard.modules.tool.service; | ||||
		Reference in New Issue
	
	Block a user
	 YunaiV
					YunaiV