跳到主要内容

ORM 框架对比

问题

Node.js 生态中有哪些主流 ORM?各有什么优缺点?

答案

主流 ORM 对比

维度PrismaTypeORMDrizzleSequelize
类型安全⭐⭐⭐ 自动生成⭐⭐ 装饰器⭐⭐⭐ SQL-like⭐ 需手写
学习曲线
查询方式自有 APIQueryBuilder / Active RecordSQL-likeActive Record
迁移Prisma Migrate内置 Migrationdrizzle-kitCLI
性能高(接近原生)中低
生态活跃成熟快速增长成熟

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?

答案

  1. 类型安全:从 Schema 自动生成 TypeScript 类型
  2. 迁移prisma migrate 自动管理数据库变更
  3. 直观 API:声明式查询,学习成本低
  4. Prisma Studio:可视化数据查看

缺点:复杂查询不如原生 SQL 灵活,有运行时 overhead(Query Engine)。

Q2: Drizzle 有什么独特优势?

答案

  1. 零运行时开销:直接生成 SQL
  2. SQL-like 语法:会写 SQL 就会用 Drizzle
  3. Bundle 小:适合 Serverless

Q3: 什么时候不用 ORM?

答案

  • 极端性能要求(使用原生 SQL + 连接池)
  • 复杂报表查询(手写 SQL 更灵活)
  • 批量数据操作(ORM 可能生成低效 SQL)

相关链接