Article summary
In a previous spin post, Sivhaun went over the basics of using PlantUML to create a database schema. That’s a really cool starting point, but it just scratches the surface of what Plant is capable of. There are a whole host of customization options that can really tailor your diagram to your specific use case. This can result in a huge improvement to the usability of writing or modifying your diagram while also making it much more readable graphically as well. Let’s dig into how to customize PlantUML.
Starting Setup
Let’s start with a simple example, using a simple database schema as an example:
@startuml
object account {
id: long not null
email: string not null
}
object user {
id: long not null
account_id: long not null
name: string
}
object session {
id: long not null
user_id: long not null
opened: timestamp not null
closed: timestamp
}
account ||--|{ user
user ||--|{ session
@enduml
Functions
This is great and all, but what if we want this to look more like a classic schema diagram? We can define our own custom entity that uses an easily recognizable symbol for a database table.
@startuml
!define table(x) entity x << (T, white) >>
table(account) {
id: long not null
email: string not null
}
table(user) {
id: long not null
account_id: long not null
name: string
}
table(session) {
id: long not null
user_id: long not null
opened: timestamp not null
closed: timestamp
}
account ||--|{ user
user ||--|{ session
@enduml
Okay, that’s pretty cool! We defined our own function that returns the standard entity header that we recognize as a database table. That’s a pretty small improvement, though. We should really make some bigger changes. It would be really nice to denote primary and foreign keys with standard recognizable symbols to really make this diagram easy to parse at a glance.
@startuml
!define table(x) entity x << (T, white) >>
!define primary_key(x) **<color:#b8861b><&key> x**
!define foreign_key(x) <color:#aaaaaa><&key> x
!define unique(x) x*
!define column(x) x
table(account) {
primary_key(id): long not null
unique(email): string not null
}
table(user) {
primary_key(id): long not null
foreign_key(account_id): long not null
column(name): string
}
table(session) {
primary_key(id): long not null
foreign_key(user_id): long not null
column(opened): timestamp not null
column(closed): timestamp
}
account ||--|{ user
user ||--|{ session
@enduml
Entity member pointers
Ok, now we’re REALLY getting somewhere. We turned all our columns into functions that can return the pre-formatted text that gives us easily identifiable schema items. Color-coded key icons identify table keys with bold signifying primary, and an asterisk denotes a unique column. One thing that still bugs me, though, is that table connections just point from one object to another. In a schema, however, actual columns point to other columns, as a foreign key has to reference an actual column in another table. Let’s see what we can do about that.
account::id ||--|{ user::account_id
user::id ||--|{ session::user_id
Well that’s pretty nice, but the curved lines look a little goofy. It would be nice to re-organize this so they were easier to see at a glance.
@startuml
left to right direction
!define table(x) entity x << (T, white) >>
!define primary_key(x) **<color:#b8861b><&key> x**
!define foreign_key(x) <color:#aaaaaa><&key> x
!define unique(x) x*
!define column(x) x
...
More Ways to Customize PlantUML
Now that’s what I call a schema diagram. It’s now pretty easy to write and add to tables, and it’s certainly easier to read these tables at a glance. The truth is that’s STILL only scratching the surface of what PlantUML can do. Not only are there LOTS more diagram types, there’s so much more you can do if you really want to dive deep into the language features of Plant. Creating variables so you don’t have to type “long not null” a million times is as easy as defining a variable !$id = "long not null"
and referencing it with $id
. You can write conditional statements, loops, add emoticons, and so much more. The next time you reach for a visual editor for diagramming, consider if you can really swap to code as visuals and never have to move and reconnect lines and graphics again!