数据库初始化
数据库初始化
本篇梳理平台所有 SQL 文件的用途,给出 MySQL 推荐导入组合,并说明 H2 自动建表机制。数据库初始化是部署中最容易踩坑的环节,请仔细对照。
一、SQL 文件总览
平台散落着多个 SQL 文件,用途与完整度各不相同:
| 文件路径 | 表数 | 用途 | 适用数据库 |
|---|---|---|---|
backend/src/main/resources/schema-h2.sql | 53 | 最完整的建表脚本,H2 自动执行 | H2(开发) |
backend/src/main/resources/data-h2.sql | - | H2 种子数据(租户/用户/角色/菜单/字典) | H2(开发) |
docs/SQL_INIT.sql | 13 | 基础表(sys_* 核心系统表 + lc_* 表/列/表单/图表元数据 + 模板) | MySQL |
docs/SQL_EXTENSION.sql | 48 | 扩展表(BPM 流程 / ERP 采购销售合同库存 / 消息通知 / 报表) | MySQL |
sql/mysql/bpm.sql | 8 | 芋道风格 BPM 表(bpm_category / bpm_form / bpm_oa_leave / bpm_process_* / bpm_user_group),含种子数据 | MySQL |
sql/mysql/hr_employee.sql | 1 | 员工档案表 hr_employee(schema-h2.sql 未含此表) | MySQL |
sql/mysql/migration-column-meta-options.sql | - | 幂等迁移:为 lc_column_meta 补 options_api 等远端选项列 | MySQL |
backend/src/main/resources/data-mysql.sql | - | 修复脚本:为 BPM 表补 create_by / update_by 列(BaseEntity 需要) | MySQL |
backend/src/main/resources/schema-mysql.sql | 16 | ⚠️ 仅 16 表,严重落后,不要单独使用 | MySQL(不推荐) |
schema-mysql.sql 不要单独用
schema-mysql.sql 只有 16 张表(少量 sys_* + lc_* 元数据),缺少 BPM、ERP、HR、权限、SSO、审计等全部业务表。单独导入会导致后端启动后大面积「表不存在」错误。MySQL 初始化请用下文推荐组合。
二、H2 自动建表(开发环境)
H2 profile 下无需手动导入任何 SQL,Spring Boot 启动时自动执行:
# application-h2.yml
spring:
sql:
init:
schema-locations: classpath:schema-h2.sql # 53 张表
data-locations: classpath:data-h2.sql # 种子数据
mode: always # 每次启动执行schema-h2.sql 是当前最完整的建表脚本,覆盖:
- 系统域 sys_*(12 表):租户、用户、角色、菜单、用户角色、角色菜单、字典类型、字典数据、SSO 提供商、SSO 绑定、部门、岗位、用户岗位
- 低代码引擎 lc_*(16 表):表元数据、列元数据、表单、列表、页面、图表、应用、菜单、数据源、表关系、报表、模块模板、开放接口配置、流程定义等
- 工作流 bpm_*(13 表):流程定义、实例、任务、会签、审批记录、分类、表单、流程定义扩展信息、表达式、抄送、监听器、用户组、OA 请假
- ERP erp_*(9 表):采购计划、采购订单、销售订单、供应商、客户、商品、仓库、库存、合同
- HR hr_*(2 表):招聘需求、面试记录
此外,com.lowcode.config.DataInitializer(CommandLineRunner)会在启动后用 JdbcTemplate 自动补建权限表(sys_role_field_permission 等)、SSO 表、AI 模型配置表、审计配置表等运行时表结构。
H2 数据会丢
H2 是内存库,进程结束数据全丢。需持久化请用 MySQL。
三、MySQL 推荐导入组合(生产)
1. 建库
CREATE DATABASE lowcode CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;2. 按顺序导入
mysql -u root -p lowcode < docs/SQL_INIT.sql
mysql -u root -p lowcode < docs/SQL_EXTENSION.sql
mysql -u root -p lowcode < sql/mysql/bpm.sql
mysql -u root -p lowcode < sql/mysql/hr_employee.sql
mysql -u root -p lowcode < backend/src/main/resources/data-mysql.sql
mysql -u root -p lowcode < sql/mysql/migration-column-meta-options.sql各文件作用说明:
① docs/SQL_INIT.sql — 基础 13 表
系统核心表与低代码元数据表,是平台运行的最小集合:
sys_tenant/sys_user/sys_role/sys_menu/sys_user_role/sys_role_menu/sys_dict_type/sys_dict_datalc_table_meta/lc_column_meta/lc_form_config/lc_chart_config/lc_module_template
② docs/SQL_EXTENSION.sql — 扩展 48 表
按域分组:
- BPM(13 表):
bpm_definition/bpm_node/bpm_flow/bpm_instance/bpm_task/bpm_task_sign/bpm_approval_record/bpm_delegate_rule/bpm_agent/bpm_category/bpm_form/bpm_favorite/bpm_notification - ERP 采购链(8 表):
erp_supplier/erp_purchase_request/erp_purchase_request_item/erp_purchase_order/erp_purchase_order_item/erp_purchase_receipt/erp_purchase_receipt_item/erp_purchase_return - ERP 销售链(8 表):
erp_customer/erp_sale_quotation/erp_sale_quotation_item/erp_sale_order/erp_sale_order_item/erp_sale_delivery/erp_sale_delivery_item/erp_sale_return - ERP 合同(4 表):
erp_contract/erp_contract_item/erp_contract_payment_plan/erp_contract_change_log - ERP 仓储库存(9 表):
erp_warehouse/erp_warehouse_area/erp_warehouse_rack/erp_product/erp_product_category/erp_inventory/erp_inventory_log/erp_stock_check/erp_stock_check_item - 消息通知(4 表):
sys_message/sys_message_receiver/sys_notice/sys_internal_message - 报表(2 表):
report_config/report_data
SQL_EXTENSION 与 schema-h2 表结构差异
SQL_EXTENSION.sql 与 schema-h2.sql 都定义了 BPM / ERP 表,但结构不完全一致:SQL_EXTENSION.sql 更细粒度(含订单明细 *_item 表、收货 erp_purchase_receipt、退货 erp_purchase_return、报价 erp_sale_quotation、盘点 erp_stock_check 等),适合完整 ERP 场景;schema-h2.sql 的 ERP 部分是精简版。MySQL 生产环境以 SQL_EXTENSION.sql 为准。
③ sql/mysql/bpm.sql — 芋道风格 BPM 8 表
文件较大(约 858KB),除建表外还含较多种子数据。定义了与芋道 BPM 集成相关的表:
bpm_category/bpm_form/bpm_oa_leave/bpm_process_definition_info/bpm_process_expression/bpm_process_instance_copy/bpm_process_listener/bpm_user_group
bpm_category / bpm_form 重复定义
bpm.sql 与 SQL_EXTENSION.sql 都定义了 bpm_category / bpm_form。导入顺序上 SQL_EXTENSION.sql 在前,bpm.sql 在后。若 bpm.sql 用了 CREATE TABLE IF NOT EXISTS 或 DROP TABLE IF EXISTS,需注意后者可能覆盖前者。如遇字段冲突报错,可手动跳过其中一个文件的重复表定义。
④ sql/mysql/hr_employee.sql — 员工档案表
CREATE TABLE hr_employee (
-- 员工档案:工号、姓名、部门、岗位、入职/转正/离职日期、状态等
...
);schema-h2.sql 中只有 hr_recruitment_demand 和 hr_interview,没有 hr_employee。MySQL 环境需单独导入此文件才能使用员工档案功能。
⑤ backend/src/main/resources/data-mysql.sql — BPM 表补列修复
并非种子数据,而是 ALTER TABLE 修复脚本。为芋道风格 BPM 表补充 create_by / update_by 列(BaseEntity 自动填充需要这两列):
ALTER TABLE bpm_category ADD COLUMN IF NOT EXISTS create_by VARCHAR(64) DEFAULT '' COMMENT '创建者';
ALTER TABLE bpm_category ADD COLUMN IF NOT EXISTS update_by VARCHAR(64) DEFAULT '' COMMENT '更新者';
-- ... 对 bpm_form / bpm_process_definition_info / bpm_process_expression 等表同样补列⑥ sql/mysql/migration-column-meta-options.sql — 列元数据补列(幂等)
为 lc_column_meta 表补充远端选项相关列(options_api / option_value / option_label / display_prop),用于 select / multiselect / tree-select 关联其他实体。脚本用 information_schema 判断列是否存在,可重复执行:
-- 幂等:列已存在则跳过
CALL lc_add_column_if_missing('lc_column_meta', 'options_api', '...');不执行此脚本的后果
若旧库未补这些列,导出工程时 MyBatis-Plus 全字段查询会报 Unknown column 'options_api'。
四、运行时自动建表
除了上述静态 SQL 文件,部分表由代码在运行时创建:
| 来源 | 创建的表 | 触发时机 |
|---|---|---|
DataInitializer(CommandLineRunner) | sys_role_field_permission / sys_role_data_permission / sys_role_button_permission / sys_audit_log / sys_config / sys_ai_model_config / sys_user_app / lc_form_version / lc_list_version / lc_api_key / lc_webhook / lc_ip_allowlist / bpm_task_follow / bpm_task_transfer_record / sys_tenant_menu 等 | 应用启动时(JdbcTemplate CREATE TABLE IF NOT EXISTS) |
FoundationSeeder | 21 张 fnd_* 实体表(基金会官网:fnd_news / fnd_project / fnd_donation / fnd_partner / fnd_publication / fnd_site_config 等;另有若干 fnd_*_status / fnd_*_type 字典类型,非实体表) | 首次访问基金会模块时按需创建 |
ErpAppSeeder | ERP 应用与字典种子数据 | 应用启动时 |
这些表没有独立 .sql 文件
上表中的表(权限表、审计表、SSO 表、AI 模型配置表、基金会官网表等)没有对应的建表 SQL 文件,DDL 写在 Java 代码里(CREATE TABLE IF NOT EXISTS)。应用启动时 DataInitializer 会自动补建,因此即使静态 SQL 文件没覆盖,启动后这些表也会存在。
五、数据源配置
MySQL(application-mysql.yml)
spring:
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/lowcode?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true
username: root
password: Admin123. # 默认,生产务必修改
hikari:
minimum-idle: 5
maximum-pool-size: 20
connection-timeout: 30000
idle-timeout: 600000
max-lifetime: 1800000
connection-test-query: SELECT 1
sql:
init:
mode: never # 关键:MySQL 不自动建表,需手动导入mode: never
application-mysql.yml 中 spring.sql.init.mode: never,意味着 Spring Boot 不会在 MySQL 下自动执行任何建表脚本。所有表结构必须手动导入。这与 H2 的 mode: always 形成对比。
H2(application-h2.yml)
spring:
datasource:
driver-class-name: org.h2.Driver
url: jdbc:h2:mem:lowcode;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE;MODE=MySQL
username: sa
password:
sql:
init:
schema-locations: classpath:schema-h2.sql
data-locations: classpath:data-h2.sql
mode: always # H2 自动建表 + 种子数据六、验证导入结果
-- 查看总表数(生产 MySQL 导入后应在 60+ 张,加上运行时自动建表可达 80+)
SELECT COUNT(*) FROM information_schema.tables
WHERE table_schema = 'lowcode';
-- 按前缀分组统计
SELECT
CASE
WHEN table_name LIKE 'sys_%' THEN 'sys_*'
WHEN table_name LIKE 'lc_%' THEN 'lc_*'
WHEN table_name LIKE 'bpm_%' THEN 'bpm_*'
WHEN table_name LIKE 'erp_%' THEN 'erp_*'
WHEN table_name LIKE 'hr_%' THEN 'hr_*'
WHEN table_name LIKE 'fnd_%' THEN 'fnd_*'
WHEN table_name LIKE 'report_%' THEN 'report_*'
ELSE '其他'
END AS domain,
COUNT(*) AS cnt
FROM information_schema.tables
WHERE table_schema = 'lowcode'
GROUP BY domain
ORDER BY cnt DESC;完整表清单与每张表的说明见 。
下一步:上线前请过一遍 。
