团队里最让人抓狂的技术债,绝对是“改了数据库结构,却从不改文档”。每次新同学在群里问某个表或者某个字段是干什么用的,老员工的回应永远是:“哦,那个字段早就废弃了,现在是用另外一个,文档还没来得及更新。”久而久之,项目里费劲维护的数据库设计文档直接沦为废纸。
靠开发人员的自觉性去手动更新文档是根本行不通的。既然我们项目里用了 Prisma 作为 ORM 框架,数据库的唯一事实来源就是 schema.prisma,那为什么不把文档生成直接做成自动化的 CI/CD 流程?
我们目前的做法是利用 prisma-markdown 这个生成器,配合 husky 和 lint-staged,在开发同学执行 git commit 的瞬间,自动解析 Prisma schema 文件,在本地渲染出最新的 Markdown 格式表结构说明和 Mermaid ER 关系图,并强行将其一起打包提交。
首先,在我们的 schema.prisma 中声明 markdown 文档生成器。这样每次运行 prisma generate 时,就会自动生成对应的文档:
datasource db {
provider = "postgresql"
url = env("DATABASE_URL")
}
generator client {
provider = "prisma-client-js"
}
// 引入 markdown 生成器
generator markdown {
provider = "prisma-markdown"
output = "../docs/database.md"
title = "核心业务系统数据库架构设计"
}
model User {
id Int @id @default(autoincrement())
email String @unique
name String?
role Role @default(USER)
posts Post[]
createdAt DateTime @default(now())
@@map("users")
}
model Post {
id Int @id @default(autoincrement())
title String
content String?
published Boolean @default(false)
authorId Int
author User @relation(fields: [authorId], references: [id])
createdAt DateTime @default(now())
@@map("posts")
}
enum Role {
USER
ADMIN
}
为了确保开发人员在提交代码前一定生成了最新的文档,我们在 package.json 中配置了对应的 npm scripts 以及 lint-staged 规则:
{
"name": "homework-money-printer-site",
"version": "1.0.0",
"scripts": {
"db:doc": "prisma generate --schema=./prisma/schema.prisma",
"prepare": "husky install"
},
"dependencies": {
"@prisma/client": "^5.10.0"
},
"devDependencies": {
"husky": "^9.0.11",
"lint-staged": "^15.2.2",
"prisma": "^5.10.0",
"prisma-markdown": "^1.0.9"
},
"lint-staged": {
"prisma/schema.prisma": [
"npm run db:doc",
"git add docs/database.md"
]
}
}
最后,在 .husky/pre-commit 钩子文件中,我们只需要添加一行极其简单的指令:
#!/bin/sh
. "$(dirname "$0")/_/husky.sh"
npx lint-staged
这样折腾完以后,任何开发人员只要修改了 schema.prisma 里的任何一个字段或表关联关系,在执行 git commit 时,Husky 就会强行拦截,并在本地启动 Prisma 编译器更新 docs/database.md。紧接着,lint-staged 会自动把这个生成的文档也加入到当前的暂存区(Git Stage)中,随同业务代码一起提交上去。
这套方案跑了几个月,数据库文档再也没有落后过库表结构。唯一需要注意的踩坑点是,prisma-markdown 自动生成的 Mermaid ER 图如果实体太多,在一些低版本的 Markdown 阅读器里可能会因为图表过大导致渲染崩溃。对于超大型项目,建议分模块配置多个 schema 文件。
你们团队是怎么保证数据库定义和设计文档保持一致的?是靠 CI 脚本强行校验,还是干脆直接看数据库实体类代码?