代码生成
这篇解决什么
建好业务表后,用基础设施的代码生成器出一套 CRUD:Controller、VO、DO、Mapper、PC 页、移动端页、菜单 SQL。读完能导入表、改生成配置、预览并下载 zip,再把文件落到对应模块。
四种模板一起讲:单表、树表、主子表(标准 / ERP / 内嵌)、移动端。默认端口 48080,管理端前缀 /admin-api。
示意图:管理端只存表定义;真正出码的是 Velocity 模板。
从哪打开
菜单在基础设施 → 代码生成。官方菜单 id 115,路由 /infra/codegen,组件 infra/codegen/index。
| 名称 | 说明 | 仓库路径 |
|---|---|---|
| 管理端页 | 列表、导入、预览、下载 | ruoyi-office-vben/apps/web-antd/src/views/infra/codegen/ |
| 编辑页 | 基本信息 / 字段信息 / 生成信息 | .../codegen/edit/index.vue,路由 /infra/codegen/edit |
| API | GET/POST/PUT/DELETE /infra/codegen/** | .../src/api/infra/codegen/index.ts |
| Controller | @RequestMapping("/infra/codegen") | ruoyi-office/yudao-module-infra/.../controller/admin/codegen/CodegenController.java |
| 解析默认配置 | 表前缀、CRUD 勾选、控件类型 | .../service/codegen/inner/CodegenBuilder.java |
| 出码 | Velocity,模板在 resources/codegen/ | .../service/codegen/inner/CodegenEngine.java |
| 配置项 | yudao.codegen.* | ruoyi-office/yudao-server/src/main/resources/application.yaml |
按钮权限:infra:codegen:query、create、update、delete、preview、download。对应菜单 id 115、1058、1056、1057、1059、1060。
内置案例在基础设施 → 代码生成案例(菜单 id 1070):单表、树表、主子表三种交互。

本系统截图:已导入的表定义。操作列是预览、生成代码、同步、编辑、删除。
表与关键类
生成器不读业务模块源码,只读两张元数据表。两张都标了 @TenantIgnore,配置跨租户共用。
| 名称 | 说明 | 仓库路径 |
|---|---|---|
infra_codegen_table | 一张业务表的生成配置 | CodegenTableDO |
infra_codegen_column | 字段怎么进新增 / 修改 / 查询 / 列表 | CodegenColumnDO |
dataSourceConfigId | 从哪套库导入,关联数据源配置 | DataSourceConfigDO |
moduleName | 一级目录,默认取表名第一个 _ 前面 | 如 system_dept → system |
businessName | 二级目录,第一个 _ 后面转小驼峰 | system_dept → dept |
className | Java 类名,默认去前缀后首字母大写 | system_dept → Dept |
templateType | 单表 / 树表 / 主表三种 / 子表 | CodegenTemplateTypeEnum |
frontType | 出哪套前端模板 | CodegenFrontTypeEnum |
scene | 管理后台或用户 App,决定 admin / app 包 | CodegenSceneEnum |
parentMenuId | 生成菜单 SQL 时的上级菜单 | 管理后台场景必填 |
masterTableId / subJoinColumnId / subJoinMany | 子表挂哪张主表、用哪列关联、一对多还是一对一 | 仅子表 |
treeParentColumnId / treeNameColumnId | 树的父编号列、节点显示名列 | 仅树表 |
className 去前缀后如果和别的 DO 撞 MyBatis Alias,在基本信息里加回前缀,例如改成 SystemDept。
表怎么设计
表名第一个 _ 前的前缀要和目标 Maven 模块一致。oa_seal_apply 会落到 yudao-module-oa,hrm_leave 会落到 yudao-module-hrm。
主键用 bigint 自增。表注释、列注释缺一不可,否则导入失败:CODEGEN_TABLE_INFO_TABLE_COMMENT_IS_NULL / CODEGEN_TABLE_INFO_COLUMN_COMMENT_IS_NULL。
系统列跟 BaseDO:creator、create_time、updater、update_time、deleted。要租户隔离再加 tenant_id。这几列默认不进新增 / 修改;create_time 仍可查询和列表展示。
内置单表示例表是 yudao_demo01_contact,字段对照 Demo01ContactDO:
| 名称 | 说明 | 仓库路径 |
|---|---|---|
id | 主键 | yudao_demo01_contact |
name | 名字 | 同上 |
sex | 性别,字典 system_user_sex | 同上 |
birthday | 出生年,Java 类型 LocalDateTime | 同上 |
description | 简介 | 同上 |
avatar | 头像 | 同上 |
树表示例 yudao_demo02_category 多一列 parent_id,根节点为 0(Demo02CategoryDO.PARENT_ID_ROOT)。
主子表示例主表 yudao_demo03_student。子表 yudao_demo03_course(student_id,一对多)、yudao_demo03_grade(student_id,一对一)。
注释必须先写进库
导入读的是数据库 COMMENT,不是 Java 注释。空注释直接失败,不会给默认文案。
导入表
点「导入」,选数据源,按表名或表描述搜。名称、描述都空且未点「加载全部」时,GET /infra/codegen/db/table/page 返回空页。已导入的表不会再出现。
确认后走 POST /infra/codegen/create-list。CodegenBuilder 按列名后缀给默认值:
| 名称 | 说明 | 仓库路径 |
|---|---|---|
name 后缀 | 查询条件 LIKE | COLUMN_LIST_OPERATION_CONDITION_MAPPINGS |
time / date 后缀 | 查询 BETWEEN,控件日期 | 同上 + COLUMN_HTML_TYPE_MAPPINGS |
status / sex 后缀 | 单选 | 同上 |
type 后缀 | 下拉 | 同上 |
image / file 后缀 | 图片 / 文件上传 | 同上 |
content / description 后缀 | 富文本 | 同上 |
Boolean | 强制单选 | processColumnUI |
LocalDateTime | 强制日期控件 | 同上 |
导入后的 scene 默认管理后台,frontType 取 yudao.codegen.front-type。同一数据源下表名重复会报 CODEGEN_TABLE_EXISTS。
编辑配置
点行内编辑进入三步:基本信息、字段信息、生成信息。提交是 PUT /infra/codegen/update。

本系统截图:第一步改表名、表描述、实体类名、作者。
字段信息里每列可改 Java 类型、属性名、CRUD 勾选、查询方式、是否允许空、显示类型、字典、Swagger 示例。
| 名称 | 说明 | 仓库路径 |
|---|---|---|
| 插入 | 新增是否传该字段 | createOperation |
| 编辑 | 修改是否传该字段 | updateOperation |
| 列表 | 表格是否展示 | listOperationResult |
| 查询 | 搜索区是否出现 | listOperation |
| 查询方式 | =、!=、比较、LIKE、BETWEEN | CodegenColumnListConditionEnum |
| 允许空 | 生成 @NotNull / @NotEmpty | nullable |
| 显示类型 | 文本、下拉、日期、上传、富文本等 | CodegenColumnHtmlTypeEnum |
| 字典类型 | 下拉 / 单选 / 复选时用的 dict_type | 关联 system_dict_type |
| 示例 | OpenAPI @Schema(example) | example |
Java 类型下拉只有 Long、String、Integer、Double、BigDecimal、LocalDateTime、Boolean。日期按 LocalDateTime 生成,业务时间戳前端用 valueFormat: 'x'。格式配对见 MyBatis 数据库。
生成信息必填:生成模板、前端类型、生成场景、上级菜单、模块名、业务名、类名称、类描述。
| 名称 | 说明 | 仓库路径 |
|---|---|---|
| 单表(增删改查) | 1,默认导入值 | CodegenTemplateTypeEnum.ONE |
| 树表(增删改查) | 2,再选父编号列、名称列 | TREE |
| 主表(标准模式) | 10,主从表同一弹窗提交 | MASTER_NORMAL |
| 主表(ERP 模式) | 11,主表、子表各自列表和表单 | MASTER_ERP |
| 主表(内嵌模式) | 12,标准模式再加列表内嵌子表 | MASTER_INNER |
| 子表 | 15,再选主表、关联列、一对多/一对一 | SUB |
前端类型下拉读字典 infra_codegen_front_type。PC 管理端用 40(Vben5 Ant Design Schema),移动端用 60(Vue3 Admin + UniApp + WOT)。yaml 默认 front-type: 20(Vue3 Element Plus),导入后改成和当前前端一致。
默认前端类型不是 web-antd
yudao.codegen.front-type 现在是 20。不改的话,zip 里是 Element Plus 页,不能直接丢进 apps/web-antd。
生成场景 1 出 controller.admin,2 出 controller.app,类名加 App 前缀。为什么 Admin / App 拆开,见 项目结构。
单表
模板保持「单表(增删改查)」。字段按需改字典、取消不必要的查询。上级菜单指到业务目录,例如系统管理。
预览、下载都点主表这一行(单表就是它自己)。案例页:

本系统截图:基础设施 → 代码生成案例 → 单表。接口 /admin-api/infra/demo01-contact。
后端对照 Demo01ContactController:SaveReqVO 创建/更新,PageReqVO 分页,RespVO 返回,DO 不直接当入参。要改成用 DO 当参数,把 yudao.codegen.vo-type 调成 20 再生成。VO 拆分理由见 VO 对象转换、数据翻译。
树表
模板改成「树表」。父编号字段选 parent_id,名称字段选 name。根节点约定 parent_id = 0。
树表不生成 PageReqVO,改生成 ListReqVO:列表按树一次拉平,前端再展开。

本系统截图:案例树表,可新增下级。接口 /admin-api/infra/demo02-category。
主子表
先导入主表和全部子表,再分别改生成信息。
主表:模板选标准 / ERP / 内嵌之一。子表:模板选「子表」,业务名建议和主表相同;关联主表、子表关联字段(如 student_id)、一对多或一对一。
| 名称 | 说明 | 仓库路径 |
|---|---|---|
| 标准 | 主从表同一弹窗一起提交 | 案例 /infra/demo/demo03-normal |
| 内嵌 | 标准之上,主表列表内嵌子表 | /infra/demo/demo03-inner |
| ERP | 主表、子表独立列表和表单 | /infra/demo/demo03-erp |
只点主表预览或下载。引擎带上所有 templateType = 15 且 masterTableId 指向它的子表。没有子表报 CODEGEN_MASTER_GENERATION_FAIL_NO_SUB_TABLE,关联列对不上报 CODEGEN_SUB_COLUMN_NOT_EXISTS。
标准、内嵌会把子表集合并进主表保存 VO(一对多字段名加 s)。主表类名或合入字段撞名会报 CODEGEN_MASTER_TABLE_NAME_DUPLICATE / CODEGEN_MASTER_TABLE_FIELD_DUPLICATE。

本系统截图:学生主表。课程一对多、班级一对一,见 Demo03CourseDO / Demo03GradeDO。
移动端
同一张表再生成一次,前端类型改成 60。模板仍按单表 / 树表 / 主子表选。引擎走 codegen/vue3_admin_uniapp/。
| 名称 | 说明 | 仓库路径 |
|---|---|---|
| 列表 | pages-{module}/{business}/index.vue | zip 内 yudao-ui-admin-uniapp/src/ |
| 搜索 | components/search-form.vue | 同上 |
| 表单 / 详情 | form/index.vue、detail/index.vue | 同上 |
| API | api/{module}/{business}/index.ts | 同上 |
| 树表面包屑 | components/breadcrumb.vue | 模板 breadcrumb_tree.vue |
拷到 ruoyi-office-uniapp/src/。还要在 src/pages/index/menu.json 加菜单,url 写成 /pages-{module}/{business}/index,并在分包 pages.json 登记。案例已挂 demo01、demo02、demo03-normal / erp / inner。
字典下拉没有 60
前端类型选项来自 infra_codegen_front_type。库里若只有 10/20/30/40,先补一条 value=60 的字典,或在库里把该表 front_type 写成 60 再预览。
预览、下载、落到工程
预览:GET /infra/codegen/preview?tableId=,弹窗按文件路径看生成结果。下载:GET /infra/codegen/download,浏览器拿到 codegen-{className}.zip。
后端文件(scene=管理后台、模块 oa、业务 seal、类 SealApply 为例):
| 名称 | 说明 | 仓库路径 |
|---|---|---|
| Controller | REST | yudao-module-oa-server/.../controller/admin/seal/SealApplyController.java |
| VO | PageReqVO / ListReqVO、SaveReqVO、RespVO | 同包 vo/ |
| DO / Mapper | 映表与查询 | dal/dataobject/seal/、dal/mysql/seal/ |
| Service | 接口 + Impl | service/seal/ |
| 错误码草稿 | 要手工并进模块常量 | yudao-module-oa-api/.../enums/ErrorCodeConstants_手动操作.java |
| 菜单 SQL | 目录、页面、按钮 | zip 内 sql/sql.sql |
PC(frontType=40)落到 yudao-ui-admin-vben/src/,再拷到 ruoyi-office-vben/apps/web-antd/src/ 的 api/、views/。import-enable=true 时还有 modules/import-form.vue。主子表额外出 modules/{子表}-form.vue / {子表}-list.vue。
拷完后端:错误码并进该模块 ErrorCodeConstants,删掉 _手动操作 文件,在目标库执行 sql/sql.sql,重启 yudao-server。PC 刷新菜单缓存。Lint 报红先格式化或跑 pnpm lint。
unit-test-enable 默认 false,不生成 ServiceImplTest 和 h2.sql。要单测再打开后重新生成。
生成器只出 CRUD
审批单据、回写台账、附件区不要指望这一次生成收工。流程表单按 BPM 单据规范补 FlowBillService、processDefinitionKey。
配置项
yudao-server 的 application.yaml:
yudao:
codegen:
base-package: ${yudao.info.base-package}
db-schemas: ${spring.datasource.dynamic.datasource.master.name}
front-type: 20
vo-type: 10
delete-batch-enable: true
unit-test-enable: false
import-enable: false| 名称 | 说明 | 仓库路径 |
|---|---|---|
front-type | 导入时的默认前端模板 | CodegenProperties |
vo-type | 10 出 VO;20 用 DO 当新增/修改/响应(分页参数仍是 VO) | CodegenVOTypeEnum |
delete-batch-enable | 是否生成批量删除 | 默认 true |
unit-test-enable | 是否生成单测和 H2 SQL | 默认 false |
import-enable | 是否生成 Excel 导入和模板下载 | 默认 false |
改这些项只影响下一次生成,不会改已经落地的代码。
同步与后续改字段
库结构变了,行内「同步」走 PUT /infra/codegen/sync-from-db。新增列写入元数据;类型 / 可空 / 主键 / 注释 / 顺序变了的列会删掉重建;库里已删的列从元数据移除。无差异时报 CODEGEN_SYNC_NONE_CHANGE。同步不改已经拷进工程的 Java / Vue。
功能已经在跑、只加一两个字段:直接改 DO、Save/Resp VO、列表和表单,不要整表重新生成再覆盖。重新生成适合还没改过的骨架。
扩展时注意
字典要前后端都登记
生成页选了字典,PC 还要在 @vben/constants 的 DICT_TYPE 加 type,页面才能出选项和标签。
不要用生成结果覆盖手改代码
第二次下载会按当前模板重写整文件。有业务逻辑的类只对照新字段手工补。
日期列生成的是 LocalDateTime。需要纯日期时,按项目约定改成 LocalDate 并加 @JsonFormat(pattern = "yyyy-MM-dd"),前端 valueFormat: 'YYYY-MM-DD'。不要把 epoch millis 和字符串格式混用。
导入表分页空着搜不到表,是接口故意的:填表名 / 描述,或点「加载全部」。
配置与操作
管理员在 基础设施 → 代码生成 导入表、改基本信息 / 字段 / 生成信息,再预览或下载 zip。保存的是 infra_codegen_table 配置,不会自动改业务库。
把 zip 落到对应 yudao-module-* 和 views/ 后才能跑。带审批的单不要只生成 CRUD。开启见 基建功能设计。截图见上文列表和编辑页。
