ORM

2026年9月6日

ORM 把对象操作映射成 SQL,少手写拼接。TypeScript 项目里 Prisma 类型生成做得完整;Drizzle 更偏「SQL 还看得见」。本篇用 Prisma + PostgreSQL。大版本之间 API 有过拆分,以你锁的 minor 文档为准。


PostgreSQL

本机安装看 官网下载,或 Docker:

docker run -d --name postgres \
  -p 5432:5432 \
  -e POSTGRES_PASSWORD=123456 \
  postgres:16
bash

默认用户 postgres。编辑器里用 Database Client 一类插件连上即可看表。


初始化 Prisma

pnpm add prisma --save-dev
pnpm add @prisma/client
# Prisma 7 起不同数据库要装对应 driver adapter,例如:
pnpm add @prisma/adapter-pg pg
npx prisma init
bash

.env

DATABASE_URL="postgresql://postgres:123456@localhost:5432/app"
bash

schema.prisma 里建模型和关系:

generator client {
  provider = "prisma-client-js"
}

datasource db {
  provider = "postgresql"
  url      = env("DATABASE_URL")
}

model User {
  id        String   @id @default(cuid())
  email     String   @unique
  name      String
  posts     Post[]
  createdAt DateTime @default(now())
  updatedAt DateTime @updatedAt
}

model Post {
  id        String   @id @default(cuid())
  title     String
  content   String
  authorId  String
  author    User     @relation(fields: [authorId], references: [id], onDelete: Cascade)
  createdAt DateTime @default(now())
  updatedAt DateTime @updatedAt
}
text

@id@unique@relationonDelete: Cascade 对应主键、唯一、外键和级联删。

npx prisma migrate dev --name init
npx prisma generate
bash

单例客户端

开发热更新不要每次 new PrismaClient(),否则连满。

import { PrismaClient } from "@prisma/client";

const globalForPrisma = globalThis as unknown as { prisma?: PrismaClient };

export const prisma = globalForPrisma.prisma ?? new PrismaClient();

if (process.env.NODE_ENV !== "production") globalForPrisma.prisma = prisma;
ts

Prisma 7 + adapter 时,按官方把 PrismaPg 传进构造函数,不要混用旧写法。


增删改查

import { prisma } from "@/lib/prisma";
import { NextRequest, NextResponse } from "next/server";

export async function GET() {
  const users = await prisma.user.findMany();
  return NextResponse.json(users);
}

export async function POST(request: NextRequest) {
  const data = await request.json();
  const user = await prisma.user.create({ data });
  return NextResponse.json(user, { status: 201 });
}

export async function PATCH(request: NextRequest) {
  const { id, ...data } = await request.json();
  const user = await prisma.user.update({ where: { id }, data });
  return NextResponse.json(user);
}

export async function DELETE(request: NextRequest) {
  const { id } = await request.json();
  await prisma.user.delete({ where: { id } });
  return NextResponse.json({ ok: true });
}
ts

服务端组件里同样可以直接 await prisma.post.findMany(),别把客户端组件接到这个单例上。

本地可用 REST Client 写 .http 文件打这些接口。密码明文入库只适合演示,正式环境要哈希。

下一篇补一些没单独开章、但上线前后常碰到的服务端事项。


参考文档