02. 数据中台:Prisma ORM 与 PostgreSQL 的深度集成
·
第一篇我们已经搭建了脚手架,并且通过浏览器可以看到shadcn的组件库的一个效果。有了脚手架下一步就是建表,过去我们用低代码开发直接创建数据模型,我们用pg的话就用命令来管理表的创建。
1 安装 ORM 核心套件
输入如下命令来完成初始化
npm install prisma --save-dev
npm install @prisma/client

安装完成后,初始化 Prisma:
npx prisma init

2. 配置数据库连接
打开项目根目录下的 .env 文件。添加我们真实的访问地址
DATABASE_URL="postgresql://postgres:123456@localhost:5432/hospital_db"

3. 编写数据模型
一套管理系统的地基是组织和用户,这两个数据是所有业务的出发点,我们先来创建机构表和用户表,设计如下表结构
// prisma/schema.prisma
generator client {
provider = "prisma-client-js"
}
datasource db {
provider = "postgresql"
}
// ==========================================
// 1. 枚举定义 (字典管理)
// ==========================================
// 人员生命周期状态
enum EmployeeStatus {
PRE_ENTRY // 待入职 (新考录)
ACTIVE // 在职 (正常)
PROBATION // 试用期
SECONDED // 借调/外派 (关系在医院,人出去了)
LEAVE // 长假 (产假/病假)
RETIRED // 退休 (但可能返聘)
RESIGNED // 离职 (完全脱离)
DISMISSED // 开除
}
// 科室/部门类型
enum DeptType {
CLINICAL // 临床科室 (心内科、骨科)
MEDICAL_TECH // 医技科室 (影像科、检验科)
ADMIN // 职能处室 (人事处、医务处)
RESEARCH // 科研机构 (实验室、研究所)
TEACHING // 教学机构 (教研室)
LOGISTICS // 后勤保障
}
// 聘用形式
enum EmploymentType {
ESTABLISHED // 在编 (正式编制)
CONTRACT // 合同制
TEMPORARY // 临时工/劳务派遣
INTERN // 实习生/规培生
}
// ==========================================
// 2. 组织架构模型 (Organization)
// ==========================================
model Department {
id String @id @default(uuid())
name String // 科室名称,如 "心血管内科"
code String? @unique // 科室编码 (HIS系统对接用)
type DeptType @default(CLINICAL)
// 树状结构设计:上级部门
parentId String?
parent Department? @relation("DeptHierarchy", fields: [parentId], references: [id])
children Department[] @relation("DeptHierarchy")
// 部门包含的人员任职记录
placements Placement[]
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
@@map("departments")
}
// ==========================================
// 3. 人员核心模型 (Personnel)
// ==========================================
model Employee {
id String @id @default(uuid())
// --- 基础信息 ---
name String // 真实姓名
employeeId String @unique // 工号 (全院唯一标识)
idCard String @unique // 身份证号 (用于唯一性校验)
phone String?
avatar String?
// --- 账号信息 (可分离,此处为简化合并) ---
username String? @unique // 登录账号 (部分后勤人员可能没账号)
password String? // 加密密码
// --- 状态与属性 ---
status EmployeeStatus @default(PRE_ENTRY) // 生命周期状态
hireType EmploymentType @default(CONTRACT) // 编制类型
joinDate DateTime? // 入职时间
// --- 关系 ---
// 一个员工可以有多个任职 (主职+兼职)
placements Placement[]
// 生命周期变动日志 (升职、调岗、退休记录)
logs EmployeeLog[]
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
@@map("employees")
}
// ==========================================
// 4. 任职关系模型 (The Link) - 解决多部门兼职
// ==========================================
model Placement {
id String @id @default(uuid())
employeeId String
departmentId String
title String // 在该部门的职务 (如: 主任、主治医师、干事)
isPrimary Boolean @default(false) // 是否为主部门 (一个人只能有一个主部门)
startDate DateTime @default(now()) // 任职开始时间
endDate DateTime? // 任职结束时间 (空代表至今)
employee Employee @relation(fields: [employeeId], references: [id], onDelete: Cascade)
department Department @relation(fields: [departmentId], references: [id])
// 复合唯一键:防止同一人在同一部门重复添加活跃任职
@@unique([employeeId, departmentId])
@@map("placements")
}
// ==========================================
// 5. 生命周期变动日志 (Audit Trail)
// ==========================================
enum ChangeType {
ENTRY // 入职
TRANSFER // 转岗/调动
PROMOTION // 晋升
SECONDMENT // 借调
RETIREMENT // 退休
EXIT // 离职
REHIRE // 返聘
}
model EmployeeLog {
id String @id @default(uuid())
employeeId String
type ChangeType
reason String? // 变动原因
operator String? // 操作人 (HR的账号)
createdAt DateTime @default(now()) // 变动发生时间
employee Employee @relation(fields: [employeeId], references: [id])
@@map("employee_logs")
}

4. 执行“同步”魔法
现在代码写好了,我们要把它变成真正的数据库表。 回到终端,运行以下命令:
npx prisma migrate dev --name init

执行成功后可以到我们的pgAdmin查看相关的表结构

5. 封装数据库单例
在 Next.js 开发环境中(npm run dev),由于热更新机制,如果直接在代码里 new PrismaClient(),每次文件修改都会新建连接,导致数据库连接数瞬间耗尽报错。
我们需要创建一个全局单例来管理连接。
新建文件 src/lib/db.ts:
import { PrismaClient } from "@prisma/client";
// 声明全局变量类型,防止 TS 报错
const globalForPrisma = globalThis as unknown as {
prisma: PrismaClient | undefined;
};
// 如果已有实例则复用,否则新建
export const db = globalForPrisma.prisma ?? new PrismaClient();
// 非生产环境下,将实例保存到全局变量中
if (process.env.NODE_ENV !== "production") globalForPrisma.prisma = db;
6. 启动可视化管理
运行如下命令
npx prisma studio
可以在浏览器里看到我们创建的表

总结
本篇我们介绍了安装数据库软件,利用ORM工具来完成数据库表的创建,后续有了数据就可以开发我们的业务逻辑了。
更多推荐
所有评论(0)