PlantUML ER diagrams: from database schema to entity relationship diagrams
ER (Entity Relationship) diagrams are the most important tool in database design. PlantUML’s ER diagram syntax turns your schema into a clean, version-controllable diagram that lives next to your code.
What is an ER Diagram ER diagrams describe entities (tables), attributes (columns), and relationships (foreign key constraints) between them. Use cases:
New project: design the database schema collaboratively
Architecture reviews: show table structure and foreign keys
Refactoring: trace dependencies before changing tables
Onboarding: show new team members the full database structure
Minimal Example 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 @startuml entity "User" as user { +id: bigint PK -- username: varchar(50) email: varchar(100) created_at: timestamp } entity "Post" as post { +id: bigint PK -- +user_id: bigint FK title: varchar(200) body: text created_at: timestamp } user ||--o{ post: writes @enduml
entity "Display" as alias declares an entity
{ -- } contains fields; + prefix = primary key
||--o{ is the relationship cardinality symbol
Relationship Cardinality The core of ER diagrams — how many A correspond to how many B:
Symbol
Meaning
PlantUML
||
exactly one
||
o{
zero or more
o{
}|
one or more
}|
o|
zero or one
o|
1 2 3 4 5 6 7 8 @startuml entity "User" as u entity "Post" as p entity "Comment" as c u ||--o{ p : writes p ||--o{ c : has @enduml
User ||--o{ Post: one User writes zero or many Posts
Post ||--o{ Comment: one Post has zero or many Comments
Entity Declaration Syntax Basic field declaration 1 2 3 4 5 6 7 entity "TableName" as alias { +fieldname: type PK ~fieldname: type FK -fieldname: type -- ← separator line description: text }
Legend: + = primary key, ~ = foreign key, - = regular field, -- = visual separator.
Primary and foreign keys 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 @startuml entity "orders" as orders { +order_id: bigint PK ~customer_id: bigint FK ~product_id: bigint FK amount: decimal(10,2) status: varchar(20) created_at: timestamp } entity "customer" as c entity "product" as p c ||..o{ orders : places p ||..o{ orders : contains @enduml
.. = dashed (weak relationship), -- = solid (strong/identifying relationship).
Full order system ER 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 @startuml hide circle skinparam linetype ortho entity "Customer" as cust { +customer_id: bigint PK -- name: varchar(100) email: varchar(200) phone: varchar(20) created_at: timestamp } entity "Order" as ord { +order_id: bigint PK -- +customer_id: bigint FK total_amount: decimal(12,2) status: varchar(20) order_date: date } entity "OrderItem" as item { +item_id: bigint PK -- +order_id: bigint FK +product_id: bigint FK quantity: int unit_price: decimal(10,2) } entity "Product" as prod { +product_id: bigint PK -- name: varchar(200) category: varchar(50) price: decimal(10,2) stock: int } cust ||--o{ ord : places ord ||--o{ item : contains prod ||--o{ item : "is in" @enduml
hide circle removes relationship endpoint dots. skinparam linetype ortho makes lines go horizontal/vertical for cleaner diagrams.
ER Diagram vs Class Diagram
Scenario
Use ER
Use Class
Database schema design
✅
❌
Describing table relationships
✅
❌
ORM entity modeling
✅
✅
Business concept modeling
❌
✅
Service interface / data structures
❌
✅
Methods and behaviors
❌
✅
Rule of thumb : databases (tables, columns, FKs) → ER; code structures (classes, methods, interfaces) → Class.
Real Case: From Database Schema to Diagram Best toolchain:
dbdiagram.io → export to PlantUML
SchemaSpy → reverse-engineer from live database
dbuml → PlantUML generator from DBML
1 2 3 4 pg_dump -h localhost -U postgres -d mydb \ --schema-only --no-owner \ > schema_raw.txt
Styling Hide fields (show only table names and relationships) 1 2 3 4 5 6 7 8 9 10 11 @startuml hide methods hide stereotypes entity "User" as u entity "Post" as p entity "Comment" as c u ||--o{ p p ||--o{ c @enduml
Color coding 1 2 3 4 5 6 7 8 9 10 11 @startuml skinparam entity { BackgroundColor #DarkSlateGray FontColor #ffffff BorderColor #2F4F4F } entity "User" as u entity "Post" as p u ||--o{ p @enduml
Common Errors
Error
Cause
Fix
Entity not found
Referenced entity alias not declared
Check alias spelling
Duplicate identifier
Same entity declared twice
Merge or remove duplicates
Relationship lines messy
Default auto layout
Add skinparam linetype ortho
Mermaid ER Comparison Mermaid also has ER support:
1 2 3 4 erDiagram CUSTOMER ||--o{ ORDER : places ORDER ||--|{ LINE-ITEM : contains PRODUCT ||--o{ LINE-ITEM : "is in"
Feature
PlantUML ER
Mermaid ER
PK/FK notation
✅ + / ~
✅
Relationship cardinalities
✅ full
✅ partial
Field types
✅
❌
Styling
✅ rich
limited
Nested entities
✅
❌
Use PlantUML for database design (full features, rich styling). Use Mermaid for quick ER in docs (no Java required).
Recap 4 things to remember:
entity "Display" as ID { +pk: type / ~fk: type / -field: type } is the standard declaration
Cardinality : || = exactly one, o{ = zero or more, }| = one or more
skinparam linetype ortho makes relationship lines clean
ER for databases; Class for code structures — don’t mix
ER diagrams are the universal language for communicating database structure — 10× more precise than prose.