做全栈的小伙伴肯定碰到过这样的痛苦:
写数据库接口时返回类型是
any
,改个字段就得全局搜索替换;数据库表结构变了,又得手动同步TypeScript类型。而ORM工具(Object-Relational Mapping),正是为了解决这些问题而生。它让数据库操作像写普通对象一样简单,还能自动同步类型定义。Node.js生态最火的两个ORM:Prisma和Drizzle,这几天天体验了一下。下面给出对比、
我一开始选择了 Prisma,因为它以新手友好著称。不过刚开始时,各种概念确实让人应接不暢:schema、push、pull、migration、generate 等等。使用一段时间后,我逐渐理解了它的工作流程。Drizzle 也遵循类似的模式,我猜其他 ORM 工具应该也大同小异。
ORM的价值
直接写SQL的最大痛点:字段变更=类型失效。
// 传统方式:字段改名直接崩溃 const result = await pool.query('SELECT user_name FROM users') console.log(result.rows[0].username) // 字段不存在! // ORM方式:类型系统实时保护 const user = await prisma.user.findFirst() console.log(user?.username) // TS直接报错:该字段已改为displayName
Prisma保姆级体验:新手友好但稍显笨重
无论选择哪个ORM,核心流程都类似:
1️⃣ 定义数据表结构 → 2️⃣ 生成类型和客户端 → 3️⃣ 同步到数据库
定义数据结构
首先是 schema,这是定义所有数据表的地方。Prisma 使用自己特有但简单的语法,文件名为 schema.prisma。这个文件同时也负责数据库连接配置:通过 connection string 连接,指定数据库类型(MySQL/PostgreSQL/MongoDB)、数据库适配器和环境变量。这些配置适用于新项目,而对于已有数据库的情况稍后会讲到。有了这些配置后,你就可以用简单的语法定义数据表了。
// schema.prisma // 要连接的数据库 datasource db { provider = "postgresql" url = env("DATABASE_URL") } // 数据库表定义 model User { id Int @id @default(autoincrement()) email String @unique password String posts Post[] }
生成类型和客户端
接下来是 generate 命令,它根据你的 schema 生成相应的类型定义,供 Prisma Client 使用。Prisma Client 是你在代码中用来与数据库交互的接口。
每次修改schema后都要执行
npx prisma generate
同步到数据库
然后是 migrate。仅仅 generate 是不够的,因为这只是让本地的 Prisma Client 知道数据表结构,数据库本身还没有更新。通过 migrate,Prisma 会根据你的 schema 自动生成并执行 SQL 文件。这些 SQL 文件可以通过 git 进行版本控制,允许你回退更改。这样你就能在开发过程中灵活调整表结构,非常方便。
npx prisma migrate dev --name add_user_table # 像写commit message一样
还有个
prisma db push
这个我一般不太用,除非我不想要数据库的数据了,就会用这招强行覆盖如果要将 Prisma 应用到现有数据库,就需要用到
pull
命令。它会根据数据库中的表结构生成对应的 schema。使用Prisma client进行数据库操作
在代码中进行数据库操作也很简单,它采用 query 语法,具体用法如下所示,你甚至不需要会写SQL!
// 创建用户(自动类型提示) const newUser = await prisma.user.create({ data: { email: "test@prisma.com", password: hashedPassword // 自动检测字符串类型 } }) // 复杂查询(嵌套查询+条件过滤) const userWithPosts = await prisma.user.findUnique({ where: { id: 1 }, include: { posts: { where: { title: { contains: "TypeScript" } } } } })
Prisma 还提供了一个名为 Prisma Studio 的网页版图形界面,用于数据库操作(其实Drizzle也有)
Drizzle:SQL老司机的春天
Drizzle 作为后起之秀,具备 ORM 的所有基本功能,工作流程也很相似。它的主要优势在于出色的性能。使用后我发现更喜欢它,原因是:首先,它的增删改查操作语法与原生 SQL 非常接近(我就可以边用边学SQL语法了),这意味着熟悉 SQL 的开发者可以快速上手;其次,它支持自由选择数据库驱动。
定义表结构
// schema.ts(用TypeScript定义!) import { pgTable, serial, varchar } from 'drizzle-orm/pg-core'; const users = pgTable('users', { id: serial('id').primaryKey(), email: varchar('email', { length: 255 }).unique(), });
查询语法
// 原生SQL风格 const result = await drizzle .select() .from(users) .where(like(users.email, "%@drizzle.com")) .limit(10);
当然也支持query语法,和Prisma类似
const result = await db.query.users.findMany({ with: { posts: true }, });
总结
这两款 ORM 各有特色,最适合自己的还是要实际使用后才知道。(跟没说一样