跳至主要內容

代码生成

2023年4月15日大约 12 分钟功能介绍功能介绍开发运营系统代码生成

用于生成前端和后端的代码,生成步骤:

写SQL创表

请参考数据库设计

配置数据源

详细参考: 数据源维护

导入表结构

将需要生成的表,导入代码生成器。导入时,会读取数据库表结构的元数据,将表名、注释、字段名、字段注释、字段类型、字段长度、不能为空、是否主键等关键的表信息读取出来,存入代码生成表。

导入表结构时,会根据application.yml中配置的信息预设一些默认值,具体如下:

# 代码生成
lamp:
  generator:
  	# 后端代码生成路径
    outputDir: /Users/tangyh/gitlab/lamp-cloud-pro-datasource-column
    # 前端代码生成路径
    frontOutputDir: /Users/tangyh/gitlab/lamp-web-pro
    # 作者
    author: zuihou
    # 表名转换为实体类类名时,是否去除表名前缀
    tablePrefix:
      - xxx_
    # 字段名转换为实体类字段名时,是否去除字段前缀
    fieldPrefix:
      - xxx_
    # 字段名转换为实体类字段名时,是否去除字段后缀
    fieldSuffix:
      - xxx_
    # 项目前缀。 若你的项目改成了 alibaba-base-server,这里就填alibaba
    projectPrefix: 'lamp'
    # 父类
    superClass: SUPER_CLASS
    packageInfoConfig: # 其他配置建议保持PackageInfoConfig中的默认值
      # 生成代码位于 src/main/java 下的基础包
      parent: 'top.tangyh.lamp'
      # lamp-util 项目的基础包
      utilParent: 'top.tangyh.basic'
      # 枚举 位于 src/main/java/{parent}/{moduleName} 下的 包名
      enumeration: 'enumeration'
      # saveVO 位于 src/main/java/{parent}/{moduleName} 下的 包名
      saveVo: 'vo.save'
      # updateVO 位于 src/main/java/{parent}/{moduleName} 下的 包名
      updateVo: 'vo.update'
      # query 位于 src/main/java/{parent}/{moduleName} 下的 包名
      pageQuery: 'vo.query'
      # resultVo src/main/java/{parent}/{moduleName} 下的 包名
      resultVo: 'vo.result'
      # 实体 位于 src/main/java/{parent}/{moduleName} 下的 包名
      entity: 'entity'
      # manager 位于 src/main/java/{parent}/{moduleName} 下的 包名
      manager: 'manager'
      # managerImpl 位于 src/main/java/{parent}/{moduleName} 下的 包名
      managerImpl: 'manager.{}impl'
      # service 位于 src/main/java/{parent}/{moduleName} 下的 包名
      service: 'service'
      # serviceImpl 位于 src/main/java/{parent}/{moduleName} 下的 包名
      serviceImpl: 'service.{}impl'
      # controller 位于 src/main/java/{parent}/{moduleName} 下的 包名
      controller: 'controller'
      # mapper 位于 src/main/java/{parent}/{moduleName} 下的 包名
      mapper: 'mapper'
      # Mapper XML 位于 src/main/resource 下的 包名
      xml: 'mapper_{}/base'
    entity-config:   # 实体类配置
      # 【实体、VO】时间类型对应策略  ONLY_DATE: java.util  SQL_PACK:java.sql  TIME_PACK: java.time
      dateType: TIME_PACK
      # 【实体】Entity类的父类
      entitySuperClass: ENTITY
      # 【实体】指定生成的主键的ID类型 (${superClass} == NONE 时,新生成的实体才生效)
      idType: INPUT
      # 【实体、VO】表字段转换为实体字段的命名策略
      columnNaming: underline_to_camel
      # 【实体、VO】生成实体类时,忽略的字段(字段名)
		  ignoreColumns:
        - xxx
      # 【实体】 是否生成字段常量
      columnConstant: false
      # 【实体、VO】是否为链式模型
      chain: true
      # 【实体、VO】 是否为lombok模型
      lombok: true
      # 【实体】乐观锁字段名称
      versionColumnName: ''
      # 【实体】乐观锁属性名称
      versionPropertyName: ''
      # 【实体】逻辑删除字段名称
      logicDeleteColumnName: ''
      # 【实体】逻辑删除属性名称
      logicDeletePropertyName: ''
      # 【实体】生成的@TableField注解上需要填充的字段和填充类型
      fillColumnName:
        - xxx: INSERT
      # 【VO】格式化SaveVO文件名称
      formatSaveVoFileName: ''
      # 【VO】格式化UpdateVO文件名称
      formatUpdateVoFileName: ''
      # 【VO】格式化ResultVO文件名称
      formatResultVoFileName: ''
      # 【VO】格式化 PageQuery 文件名称
      formatPageQueryFileName: ''
    mapperConfig:   # mapper类配置
   		# 格式化Mapper文件名称
      formatMapperFileName: ''
      # 格式化Xml文件名称
      formatXmlFileName: ''
      # 是否添加 @Mapper 注解(默认 false)
      mapperAnnotation: false
      # mapper类上是否添加忽略表结构 @InterceptorIgnore
      columnAnnotationTablePrefix:
        - 表的前缀
      # 生成的xml中,是否包含BaseResultMap(默认 false)  
      baseResultMap: true
    serviceConfig:
      # 继承的Service类全称,带包名
      superServiceClass: top.tangyh.basic.base.service.SuperService
      # 继承的ServiceImpl类全称,带包名
      superServiceImplClass: top.tangyh.basic.base.service.impl.SuperServiceImpl
      # 格式化service接口文件名称
      formatServiceFileName: '{}Service'
      # 格式化service实现类文件名称
      formatServiceImplFileName: ''
      # 匹配到此前缀的表,生成的 serviceImpl 类上会自动添加切换数据源注解 @DS
      dsTablePrefix: 
      	- xxx
    managerConfig:
      # 继承的Manager类全称,带包名
      superManagerClass: 'top.tangyh.basic.base.manager.SuperManager'
      # 继承的ManagerImpl类全称,带包名
      superManagerImplClass: 'top.tangyh.basic.base.manager.impl.SuperManagerImpl'
      # 格式化Manager接口文件名称
      formatManagerFileName: ''
      # 格式化Manager实现类文件名称
      formatManagerImplFileName: ''
    controllerConfig:
    	# 生成 @RestController 控制器(默认 false)
      restStyle: true
      # 格式化文件名称
      formatFileName: ''
      # 驼峰转连字符
      hyphenStyle: false  
      # 继承的Controller类全称,带包名
      superClass: 'top.tangyh.basic.base.controller.SuperController'
    webProConfig:
    	# 格式化菜单文件名称
      formatMenuName: {}维护
      # 前端生成页面样式模板
      tpl: SIMPLE
    fileOverrideStrategy:  # 文件覆盖策略
      entityFileOverride: OVERRIDE
      sqlFileOverride: OVERRIDE
      mapperFileOverride: EXIST_IGNORE
      xmlFileOverride: OVERRIDE
      managerFileOverride: EXIST_IGNORE
      serviceFileOverride: EXIST_IGNORE
      controllerFileOverride: EXIST_IGNORE
      apiModelFileOverride: OVERRIDE
      langFileOverride: OVERRIDE
      indexEditTreeFileOverride: EXIST_IGNORE
      dataFileOverride: EXIST_IGNORE
    constantsPackage:   # 公共枚举的完整类名,配置后自定义的枚举类才能正常 import
      # 业务服务 后台手动改动过的枚举
      FieldFill: com.baomidou.mybatisplus.annotation.FieldFill
      SuperClassEnum: top.tangyh.lamp.generator.enumeration.SuperClassEnum
      EntitySuperClassEnum: top.tangyh.lamp.generator.enumeration.EntitySuperClassEnum
      # common 常量
      EchoDictType: top.tangyh.lamp.model.constant.EchoDictType
      EchoApi: top.tangyh.lamp.model.constant.EchoApi
      # common 公共枚举
      HttpMethod: top.tangyh.lamp.model.enumeration.HttpMethod
      BooleanEnum: top.tangyh.lamp.model.enumeration.BooleanEnum
      StateEnum: top.tangyh.lamp.model.enumeration.StateEnum
      UserStatusEnum: top.tangyh.lamp.model.enumeration.base.UserStatusEnum
      RoleCategoryEnum: top.tangyh.lamp.model.enumeration.base.RoleCategoryEnum
      ActiveStatusEnum: top.tangyh.lamp.model.enumeration.base.ActiveStatusEnum
      OrgTypeEnum: top.tangyh.lamp.model.enumeration.base.OrgTypeEnum
      FileType: top.tangyh.lamp.model.enumeration.base.FileType
      DateType: top.tangyh.lamp.model.enumeration.base.DateType
      DictClassifyEnum: top.tangyh.lamp.model.enumeration.system.DictClassifyEnum
      DefTenantStatusEnum: top.tangyh.lamp.model.enumeration.system.DefTenantStatusEnum
      DataTypeEnum: top.tangyh.lamp.model.enumeration.system.DataTypeEnum
      TenantConnectTypeEnum: top.tangyh.lamp.model.enumeration.system.TenantConnectTypeEnum

配置生成信息

用于配置生成的代码存放路径、文件名、代码结构等信息。

  1. 服务名

    • 确保前端ServicePrefixEnum中的枚举值KEY 与 后端“服务名”和lamp-gateway-server.yml中“uri”保持一致

    • 确保前端ServicePrefixEnum中的枚举值VALUE 与 后端lamp-gateway-server.yml中“predicates”配置一致

    • 如: lamp-base、lamp-base-api、lamp-base-biz、lamp-base-controller、lamp-base-server 中的 base

    • 如: lamp-system-server 中的 system

  2. 父包名

    生成业务代码的基础包包名。如:"top.tangyh.lamp.base.dao.common" 中的 "top.tangyh.lamp"

  3. 模块名

    建议跟{服务名}保持一致。如:

    • "top.tangyh.lamp.base.dao.common" 中的 "base"

    • "top.tangyh.lamp.file.dao" 中的 "file"

  4. 子包名

    • "top.tangyh.lamp.base.dao.common" 中的 "common"

    • "top.tangyh.lamp.base.dao.system" 中的 "system"

  5. 实体父类

    实体类需要继承谁,参考:EntitySuperClassEnum

  6. 父类

    Controller、Service、Manager、Mapper类需要继承谁,参考:SuperClassEnum

  7. @DS

    ServiceImpl类是否标记@DS注解,加上该注解后,sql操作会自动切换数据源。

    datasource模式才会使用该参数,column、none模式请忽略。

  8. 数据源

    @DS选是,ServiceImpl类标记的@DS注解具体值

  9. @TenantLine

    Mapper类是否标记@TenantLine注解,加上该注解sql操作不会自动拼接租户ID。

    column模式才会使用该参数,datasource、none模式请忽略。

  10. lombok

    实体类是否使用Lombok注解

  11. 链式模型

    实体类是否使用@Accessors(chain = true)注解

  12. 生成字段常量

    实体类中是否生成字段常量

  13. 后端生成路径

  14. 前端生成路径

  15. 前端应用名

    • src/views/ 目录下的 basic 或 devOperation 或 “其他”

    • src/api/ 目录下的 basic 或 devOperation 或 “其他”

    • src/locales/lang/{语言}/ 目录下的 basic 或 devOperation 或 “其他”

    • “其他” 表示其他应用

  16. 前端模块名

    • src/api/{前端应用名} 目录下的文件夹名

    • src/views/{前端应用名} 目录下的文件夹名

    • src/locales/lang/{语言}/{前端应用名} 目录下的文件夹名

    • 如: src/views/devOperation/ 下的 application、developer 等目录

    • 如: src/api/devOperation/ 下的 application、developer 等目录

  17. 弹窗方式

    前端代码index.vue页面点击新增或编辑时,弹窗的打开方式

  18. 生成模板

    前端代码生成何种操作风格的页面

  19. 显示[新增|编辑|删除|复制|详情]按钮

    生成的前端页面,是否包含新增、编辑、删除、复制、详情等按钮

  20. [新增|编辑|删除|复制|详情]按钮权限

    生成的前端页面,新增、编辑、删除、复制、详情等按钮是否控制按钮权限

  21. 菜单所属应用

    当前功能生成后,菜单属于哪个应用?

  22. 上级菜单

    当前功能生成后,显示在左侧菜单的位置

  23. 当前菜单名

    当前功能生成后,显示在左侧的菜单名

  24. 菜单图标

    当前功能生成后,显示在左侧的菜单图标

配置字段信息

用于配置生成的实体类字段的信息,默认值来源于导入时,读取表结构元数据信息。

  1. 列名称

    字段的原始名称

    提示

    “原始”的意思是,数据库表结构中是什么这里就存什么。

  2. 列类型

    字段的原始数据库类型

  3. 列描述

    字段的原始注释。在生成代码时,会将列描述生成到字段的注释中。

  4. 文档描述

    体现在Swagger注解上的注释。导入时,将列描述截取;前的字符作为文档描述。实现代码:

    /**
     * @param comment 列描述
     */
    private static String getSwaggerComment(String comment) {
        String swaggerComment = StrUtil.isBlank(comment) ? StrUtil.EMPTY : StrUtil.trim(comment);
        if (swaggerComment.contains(StrPool.SEMICOLON)) {
            swaggerComment = StrUtil.subBefore(swaggerComment, StrPool.SEMICOLON, false);
        }
        // 若含有换行符,替换为空格
      	// \n 是mysql注释中的换行符,其他数据库的换行符需要自己改这里代码适配下
        swaggerComment = StrUtil.replace(swaggerComment, "\n", " ");
        return swaggerComment;
    }
    
  5. JAVA类型

    根据列类型自动映射的Java字段类型。

    public static DefGenTableColumn initColumnField(GeneratorConfig generatorConfig, DbType dbType, DefGenTable genTable, Column column) {
        ITypeConvert typeConvert = TypeConverts.getTypeConvert(dbType);
        ColumnType columnType = typeConvert.processTypeConvert(entityConfig.getDateType(), column.getTypeName(), column.getSize(), column.getDigit());
        
      	// JAVA类型
      	tableColumn.setJavaType(columnType.getType());
      	// TS类型
        tableColumn.setTsType(columnType.getTsType());
    }
    
  6. TS类型

    根据列类型按照一定的规则转换为前端TS语法类型。

  7. JAVA字段名

    根据列名称按照一定的规则转换为Java实体类和VO类的字段名。

    /**
     * @param name     列名称
     * @param strategy 策略
     * @param prefix   前缀
     * @param suffix   后缀
     * @return java.lang.String
     * @date 2023/4/16 10:45 PM
     */
    private static String processName(String name, NamingStrategy strategy, List<String> prefix, List<String> suffix) {
        String propertyName = name;
        // 删除前缀
        if (prefix.size() > 0) {
            propertyName = NamingStrategy.removePrefix(propertyName, prefix);
        }
        // 删除后缀
        if (suffix.size() > 0) {
            propertyName = NamingStrategy.removeSuffix(propertyName, suffix);
        }
        if (StringUtils.isBlank(propertyName)) {
            throw new RuntimeException(String.format("%s 的名称转换结果为空,请检查是否配置问题", name));
        }
        // 下划线转驼峰
        if (NamingStrategy.underline_to_camel.equals(strategy)) {
            return NamingStrategy.underlineToCamel(propertyName);
        }
        return propertyName;
    }
    
  8. 必填

    表示该字段是否必填字段,会在生成的SaveVO和UpdateVO中生成@NotEmpty@NotNull注解。

  9. 长度

    字段长度。字符串类型、SHORT、BYTE,会自动在SaveVO、UpdateVO的字段上标记@Size(max={长度}) 注解用于表单校验。

    <!-- saveVO.java.ftl、updateVO.java.ftl -->
    <#if field.javaType == "String">
    @Size(max = ${field.size?string("##0")}, message = "${field.swaggerComment!}长度不能超过${r'{max}'}")
    <#else>
        <#if field.type?upper_case?starts_with("SHORT")>
    @Size(min = Short.MIN_VALUE, max = Short.MAX_VALUE, message = "${field.customMap.fieldComment!}大小不能超过${r'{max}'}")
        </#if>
        <#if field.type?upper_case?starts_with("BYTE")>
    @Size(min = Byte.MIN_VALUE, max = Byte.MAX_VALUE, message = "${field.customMap.fieldComment!}大小不能超过${r'{max}'}")
        </#if>
    </#if>
    private ${field.javaType} ${field.javaField};
    
  10. 主键

    生成代码时,该字段是否为注解。

    <!-- entity.java.ftl -->
    
    <#list fields as field>
        /**
         * ${field.comment!?replace("\n","\n     * ")}
         */
    <#if field.isPk>
        <#-- 
             主键: 使用 @TableId
             自增: type = IdType.AUTO
             -->
        @TableId(value = "${field.name}"<#if field.isIncrement>, type = IdType.AUTO<#elseif entityConfig.idType??>, type = IdType.${entityConfig.idType}</#if>)
    <#else>
        @TableField(value = "${field.name}"<#if field.fill?? && field.fill?trim != ''>, fill = FieldFill.${field.fill}</#if><#if field.queryType?? && field.queryType?trim != ''>, condition = ${field.queryType}<#else></#if>)
    </#if>
    <#-- 乐观锁 -->
    <#if field.isVersionField>
        @Version
    </#if>
    <#-- 逻辑删除 -->
    <#if field.isLogicDeleteField>
        @TableLogic
    </#if>
        private ${field.javaType} ${field.javaField};
    </#list>
    

    注意

    若你的实体类已经继承了Entity和SuperEntity,主键属性请保持默认值,否则生成的代码可能无法运行。

    因为代码生成器只负责根据模板生成代码,不负责检查代码逻辑是否正确,若由于你配置错误,导致生成出来的代码无法运行,属于正常现象。

  11. 自增

    若该字段配置为主键,还可以配置是否自增。

  12. 逻辑删除

    标记该字段是否逻辑删除字段

    注意

    代码生成器只负责在该字段上生成注解,不负责代码执行时的逻辑删除功能,功能如何实现请参考mybaits-plus官方文档open in new window配置。

  13. 乐观锁

    标记该字段是否乐观锁字段

    注意

    代码生成器只负责在该字段上生成注解,不负责实现代码的乐观锁功能,功能如何实现请参考mybaits-plus官方文档open in new window配置。

  14. 填充类型

    字段的填充类型。参考mybaits-plus文档open in new window

    @TableField(fill = FieldFill.${field.fill})

  15. 查询方式

    可选值: like、eq 。参考mybaits-plus文档open in new window

    @TableField(condition = ${field.queryType})

  16. 编辑

    是否将该字段生成到前端编辑页 表单。

  17. 列表

    是否将该字段生成到前端列表页 表格字段。

  18. 查询

    是否将该字段生成到前端列表页 查询条件区域。

  19. 宽度

    生成的字段在前端表格上显示时的宽度。

  20. 组件

    生成的字段在前端表单显示什么组件样式。 参考vben官方文档open in new window

  21. VxeTable组件

    生成的字段在前端vxe-table显示什么组件样式。 参考vxe-table官方文档open in new window

  22. Echo

    生成的字段如何回显。

    EchoType echoType = CommentUtils.getEchoType(column.getComment());
    if (echoType != null) {
      	// Echo
        tableColumn.setEchoStr(echoType.getEchoStr());
      	// 字典类型
        tableColumn.setDictType(echoType.getDictType());
    }
    // 解析注释中的枚举类型
    EnumType enumType = CommentUtils.getEnumStr(genTable.getEntityName(), tableColumn.getJavaField(), entityConfig.getFormatEnumFileName(), tableColumn.getSwaggerComment(), column.getComment());
    if (enumType != null) {
        tableColumn.setEnumStr(enumType.getEnumStr());
        tableColumn.setJavaType(enumType.getEnumName());
      	// 枚举类型的回显注解固定值
        tableColumn.setEchoStr("@Echo(api = Echo.ENUM_API)");
        tableColumn.setTsType("string");
    
        tableColumn.setComponent(ComponentEnum.PLUS_API_RADIO_GROUP.getValue());
        tableColumn.setVxeComponent(VxeComponentEnum.$RADIO.getValue());
        tableColumn.setQueryType(SqlConditionEnum.EQUAL);
    }
    
  23. 字典类型

    生成的字段需要回显,且为字典类型时,配置该字段的枚举类型。

  24. 枚举

    生成的字段为枚举类型时,字段注释中的值。

  25. 默认值

    显示在前端表单中的默认值。

  26. 提示信息

    前端表单中的感叹号提示信息。

  27. 主页提示信息

    前端表格的表头上的感叹号提示信息。

预览

根据前面步骤总配置的信息,实时预览生成的前端、后端、SQL语句等代码。

本地生成或远程下载

可以分别生成或下载前端或后端的代码。

生成策略

👆🏻👆🏻👆🏻上面是评论区,对系统、本页文档什么疑问,可以在评论区留言。
❗️❗️❗️若评论区无法显示,请使用"手机热点"或"科学上网"。
5.0.4已发布: