ORM 干什么
数据库表 ↔ JS / TS 对象的转换层 + 类型安全 + 迁移管理。
主流:
| ORM | 风格 | 特点 |
|---|---|---|
| Prisma | Schema 文件 + 生成 client | 最受欢迎、文档好、TS 一等公民 |
| Drizzle | TypeScript schema | 更轻量、类似 SQL 的链式 API |
| TypeORM | 装饰器 + 类 | 老牌、Java 风 |
| Sequelize | model 定义 | Express 时代最流行 |
| Knex | Query Builder(不算完整 ORM) | 灵活、低层 |
新项目 TS 推荐 Prisma 或 Drizzle。
Prisma
npm install -D prisma
npm install @prisma/client
npx prisma init
Schema 文件(schema.prisma)
datasource db {
provider = "postgresql"
url = env("DATABASE_URL")
}
generator client {
provider = "prisma-client-js"
}
model User {
id Int @id @default(autoincrement())
email String @unique
name String
age Int?
posts Post[]
createdAt DateTime @default(now())
}
model Post {
id Int @id @default(autoincrement())
title String
content String?
authorId Int
author User @relation(fields: [authorId], references: [id])
}
迁移 + 生成 client
npx prisma migrate dev --name init # 建迁移 + 应用
npx prisma generate # 生成 TS client
用
import { PrismaClient } from '@prisma/client';
const prisma = new PrismaClient();
// 创建
const user = await prisma.user.create({
data: { email: 'a@x.com', name: 'Alice' },
});
// 查询
const users = await prisma.user.findMany({
where: { age: { gte: 18 } },
orderBy: { name: 'asc' },
take: 20,
});
// 关联(include / select)
const userWithPosts = await prisma.user.findUnique({
where: { id: 1 },
include: { posts: true },
});
// 更新
await prisma.user.update({
where: { id: 1 },
data: { age: 31 },
});
// 删除
await prisma.user.delete({ where: { id: 1 } });
// 事务
await prisma.$transaction(async (tx) => {
await tx.user.update({ ... });
await tx.post.create({ ... });
});
// 原生 SQL
const rows = await prisma.$queryRaw`SELECT * FROM users WHERE id = ${42}`;
所有方法返回值都有完整 TS 类型——这是 Prisma 最大卖点。
Drizzle
npm install drizzle-orm
npm install -D drizzle-kit
Schema(TS)
import { pgTable, serial, varchar, integer } from 'drizzle-orm/pg-core';
export const users = pgTable('users', {
id: serial('id').primaryKey(),
email: varchar('email', { length: 255 }).unique().notNull(),
name: varchar('name', { length: 100 }).notNull(),
age: integer('age'),
});
export const posts = pgTable('posts', {
id: serial('id').primaryKey(),
title: varchar('title').notNull(),
authorId: integer('author_id').references(() => users.id),
});
用
import { drizzle } from 'drizzle-orm/postgres-js';
import { eq, gte, and } from 'drizzle-orm';
import postgres from 'postgres';
import { users, posts } from './schema';
const sql = postgres(process.env.DATABASE_URL);
const db = drizzle(sql);
// 插入
const [user] = await db.insert(users).values({
email: 'a@x.com', name: 'Alice', age: 30,
}).returning();
// 查
const list = await db.select().from(users).where(gte(users.age, 18));
// 关联
const withPosts = await db
.select()
.from(users)
.leftJoin(posts, eq(users.id, posts.authorId));
// 更新
await db.update(users).set({ age: 31 }).where(eq(users.id, 1));
// 删
await db.delete(users).where(eq(users.id, 1));
// 事务
await db.transaction(async (tx) => {
await tx.insert(users).values({ ... });
await tx.insert(posts).values({ ... });
});
Drizzle 风格更贴近 SQL——查询能力强、生成的 SQL 更可预测。
Prisma vs Drizzle
| 维度 | Prisma | Drizzle |
|---|---|---|
| 类型安全 | ★★★★★ | ★★★★★ |
| Schema 形式 | 单独 DSL 文件 | TS 代码 |
| 学习曲线 | 低 | 中 |
| 性能 | 良 | 优(生成 SQL 直接,无 runtime overhead) |
| 复杂查询 | 较弱(用 raw 补) | 强(接近 SQL) |
| 迁移 | 内置 | 内置 |
| Bundle 大小 | 较大 | 小 |
| 生态 | 大 | 增长中 |
简单项目用 Prisma(更友好),复杂 SQL / 性能敏感用 Drizzle。
迁移
# Prisma
npx prisma migrate dev --name add_user_age # 开发
npx prisma migrate deploy # 生产部署
# Drizzle
npx drizzle-kit generate # 生成迁移
npx drizzle-kit migrate # 应用
何时不用 ORM
- 极简项目(直接 SQL 更快)
- 极致性能(ORM 总有些开销)
- 复杂分析查询(ORM 翻译易出错)
这些场景用原生 pg / postgres.js + 手写 SQL 更直接。
坑
- ORM 生成的 SQL 不总是最优——慢查询要
EXPLAIN ANALYZE看 - N+1 查询陷阱(每个对象单独查一次关联)—— 用
include/join - 字段名 vs 列名容易混淆——schema 里定义清楚
- 迁移生产前必须演练——schema 改动可能锁表
下一篇:测试。