PlantUML ER 图:数据建模与表关系

puml.online

ER 图 / 数据模型图通常是数据库设计的第一步。PlantUML 在这块语法比 Mermaid 略弱,但能用,且能跟其他 UML 图保持一致风格。

一句话定义

ER 图描绘数据库表(实体)之间的关联关系:1:1 / 1:N / N:M、弱实体、派生属性。它是从领域模型物理模型过渡的标准图。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
@startuml
hide circle

entity User {
*id : BIGINT <<PK>>
--
*email : VARCHAR(255) <<UK>>
name : VARCHAR(100)
status : ENUM('active', 'banned', 'pending')
created_at : TIMESTAMP
}

entity Order {
*id : BIGINT <<PK>>
--
*user_id : BIGINT <<FK>>
*status : ENUM('pending', 'paid', 'shipped', 'delivered', 'cancelled')
total : DECIMAL(10,2)
created_at : TIMESTAMP
}

entity OrderItem {
*id : BIGINT <<PK>>
--
*order_id : BIGINT <<FK>>
*product_id : BIGINT <<FK>>
quantity : INT
unit_price : DECIMAL(10,2)
}

entity Product {
*id : BIGINT <<PK>>
--
*sku : VARCHAR(50) <<UK>>
name : VARCHAR(255)
price : DECIMAL(10,2)
stock : INT
}

User ||--o{ Order : 创建
Order ||--|{ OrderItem : 包含
Product ||--o{ OrderItem : 出现在

note top of User
ER 图符号:
|| —— 恰好一个
|o —— 0 或 1
}o —— 多
{ —— 必填
end note
@enduml

三种核心关系符号

1
2
3
4
5
A ||--|| B        : A 对 B 一对一(exactly)
A ||--o{ B : A 对 B 一对多(A 端多实例,B 端可有 0 个)
A }o--o{ B : A 对 B 多对多
A ||--|{ B : A 对 B 一对多(B 端必须至少一个)
A }|--|{ B : A 对 B 多对多(A、B 至少一个)

记忆口诀:

左侧 右侧 表示
` `
` `
` `
}o }o 多对多

衍生关系

自关联

1
2
3
4
5
6
7
8
9
10
11
12
13
@startuml
hide circle

entity Employee {
*id : BIGINT <<PK>>
--
name : VARCHAR
*manager_id : BIGINT <<FK>>
}

Employee ||--o{ Employee : 管理

@enduml

员工表「manager_id」指向自己的「id」,表达上下级关系。

派生属性(虚线边框或省略号)

PlantUML 不直接支持「派生」标记。但可以用 <<computed>> 或者用注释说明:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
@startuml
entity Order {
*id : BIGINT <<PK>>
--
*user_id : BIGINT <<FK>>
subtotal : DECIMAL(10,2)
tax : DECIMAL(10,2)
--
total : DECIMAL(10,2) <<computed>>
}

note right of Order
total = subtotal + tax
触发器或者应用层维护
end note
@enduml

多对多的连接表

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
@startuml
hide circle

entity Student {
*id : BIGINT <<PK>>
name : VARCHAR
}

entity Course {
*id : BIGINT <<PK>>
title : VARCHAR
}

entity Enrollment {
*id : BIGINT <<PK>>
--
*student_id : BIGINT <<FK>>
*course_id : BIGINT <<FK>>
grade : DECIMAL(5,2)
enrolled_at : TIMESTAMP
}

Student ||--o{ Enrollment : "报名"
Course ||--o{ Enrollment : "被报名"
@enduml

连接表(也叫「关联表」「联结表」)描述多对多关系。

实战:博客系统数据模型

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
@startuml
hide circle

entity User {
*id : BIGINT <<PK>>
--
*email : VARCHAR(255) <<UK>>
name : VARCHAR(100)
bio : TEXT
role : ENUM('admin','editor','member')
created_at : TIMESTAMP
updated_at : TIMESTAMP
}

entity Post {
*id : BIGINT <<PK>>
--
*author_id : BIGINT <<FK>>
*slug : VARCHAR(255) <<UK>>
*title : VARCHAR(500)
*body : TEXT
*status : ENUM('draft','published','archived')
published_at : TIMESTAMP
created_at : TIMESTAMP
updated_at : TIMESTAMP
}

entity Tag {
*id : BIGINT <<PK>>
--
*name : VARCHAR(50) <<UK>>
description : VARCHAR(255)
}

entity PostTag {
*post_id : BIGINT <<FK>>
*tag_id : BIGINT <<FK>>
--
}

entity Comment {
*id : BIGINT <<PK>>
--
*post_id : BIGINT <<FK>>
*author_id : BIGINT <<FK>>
*body : TEXT
created_at : TIMESTAMP
}

User ||--o{ Post : "撰写"
User ||--o{ Comment : "留下"
Post ||--o{ Comment : "拥有"
Post ||--o{ PostTag : "被分入"
Tag ||--o{ PostTag : "标记"
@enduml

评审 checklist

  • 主键用了 <<PK>> 标记?
  • 外键用了 <<FK>> 标记?
  • 唯一索引用了 <<UK>> 标记?
  • 关系比例用对了符号?||--o{ vs ||--|{ 不要混
  • 表名 / 列名规范?
  • 多对多关系有连接表?
  • 自关联有清晰说明?

工具对比

工具 优势 劣势
PlantUML ER 文本化,diff 友好,统一 PlantUML 风格 复杂布局一般
Mermaid erDiagram GitHub 原生渲染 语法有限
draw.io WYSIWYG,自由布局 文件不是文本
dbdiagram.io 专门的 ER DSL 输出 PNG/SVG 不能 merge
MySQL Workbench / DataGrip 完整 DDL 双向 重,需要 Java / 桌面安装

实战:从 ER 图生成 SQL DDL

PlantUML 不直接生成 DDL,但你可以把 ER 图作为「设计文件」,CI 用 script 生成 DDL(之后用 Flyway / Liquibase 跑迁移):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# .github/workflows/db-from-er.yml
name: Generate DDL from ER
on:
paths: ['docs/erd/**']

jobs:
ddl:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Render ER diagrams
run: |
# 自动将 .puml ER 图转 .svg 供 review
...
- name: Hand-write / review migrations
if: github.event_name == 'pull_request'
run: |
# CI 检查 docs/erd/*.puml 与 migrations/*.sql 一致
...

注意:ER 图 → DDL 不是无脑的。索引、约束、默认值、字符集都要追加,由 DBA 或者迁移工具决定。

  • 标题: PlantUML ER 图:数据建模与表关系
  • 作者: puml.online
  • 创建于 : 2026-07-29 15:35:00
  • 更新于 : 2026-08-14 21:34:29
  • 链接: https://puml.online/blog/plantuml-er/
  • 版权声明: 本文章采用 CC BY-NC-SA 4.0 进行许可。