ORM 框架对比
问题
Node.js 生态中有哪些主流 ORM?各有什么优缺点?
答案
主流 ORM 对比
| 维度 | Prisma | TypeORM | Drizzle | Sequelize |
|---|---|---|---|---|
| 类型安全 | ⭐⭐⭐ 自动生成 | ⭐⭐ 装饰器 | ⭐⭐⭐ SQL-like | ⭐ 需手写 |
| 学习曲线 | 低 | 中 | 低 | 中 |
| 查询方式 | 自有 API | QueryBuilder / Active Record | SQL-like | Active Record |
| 迁移 | Prisma Migrate | 内置 Migration | drizzle-kit | CLI |
| 性能 | 中 | 中 | 高(接近原生) | 中低 |
| 生态 | 活跃 | 成熟 | 快速增长 | 成熟 |
Prisma
prisma-example.ts
// schema.prisma
// model User {
// id String @id @default(uuid())
// name String
// email String @unique
// posts Post[]
// }
// 自动生成类型安全的 Client
import { PrismaClient } from '@prisma/client';
const prisma = new PrismaClient();
// 查询
const users = await prisma.user.findMany({
where: { name: { contains: 'Alice' } },
include: { posts: true }, // 关联查询
orderBy: { createdAt: 'desc' },
take: 10,
});
// 创建(带关联)
const user = await prisma.user.create({
data: {
name: 'Bob',
email: 'bob@example.com',
posts: {
create: [{ title: 'Hello World' }],
},
},
});
// 事务
await prisma.$transaction([
prisma.account.update({ where: { id: 1 }, data: { balance: { decrement: 100 } } }),
prisma.account.update({ where: { id: 2 }, data: { balance: { increment: 100 } } }),
]);
Drizzle
drizzle-example.ts
import { drizzle } from 'drizzle-orm/node-postgres';
import { pgTable, serial, varchar, integer } from 'drizzle-orm/pg-core';
import { eq, gt, and } from 'drizzle-orm';
// Schema 定义(TypeScript 原生)
const users = pgTable('users', {
id: serial('id').primaryKey(),
name: varchar('name', { length: 100 }).notNull(),
age: integer('age'),
});
const db = drizzle(pool);
// SQL-like 查询(接近原生 SQL 的直觉)
const result = await db
.select()
.from(users)
.where(and(eq(users.name, 'Alice'), gt(users.age, 18)))
.orderBy(users.name)
.limit(10);
// JOIN
const result2 = await db
.select({ userName: users.name, postTitle: posts.title })
.from(users)
.leftJoin(posts, eq(users.id, posts.userId));
TypeORM
typeorm-example.ts
import { Entity, PrimaryGeneratedColumn, Column, ManyToOne } from 'typeorm';
@Entity()
class User {
@PrimaryGeneratedColumn()
id!: number;
@Column()
name!: string;
@Column({ unique: true })
email!: string;
@OneToMany(() => Post, post => post.author)
posts!: Post[];
}
// QueryBuilder
const users = await userRepo
.createQueryBuilder('user')
.leftJoinAndSelect('user.posts', 'post')
.where('user.age > :age', { age: 18 })
.orderBy('user.name')
.getMany();
常见面试问题
Q1: 为什么推荐 Prisma?
答案:
- 类型安全:从 Schema 自动生成 TypeScript 类型
- 迁移:
prisma migrate自动管理数据库变更 - 直观 API:声明式查询,学习成本低
- Prisma Studio:可视化数据查看
缺点:复杂查询不如原生 SQL 灵活,有运行时 overhead(Query Engine)。
Q2: Drizzle 有什么独特优势?
答案:
- 零运行时开销:直接生成 SQL
- SQL-like 语法:会写 SQL 就会用 Drizzle
- Bundle 小:适合 Serverless
Q3: 什么时候不用 ORM?
答案:
- 极端性能要求(使用原生 SQL + 连接池)
- 复杂报表查询(手写 SQL 更灵活)
- 批量数据操作(ORM 可能生成低效 SQL)
相关链接
- 数据库连接 - Node.js 数据库连接
- NestJS 框架深入 - NestJS + TypeORM/Prisma