前言
在现代 Web 开发中,Next.js 配合 PostgreSQL 数据库已经成为了构建全栈应用的黄金搭档。而 Drizzle ORM 凭借其"无头"、类型安全且接近原生 SQL 的特性,正迅速成为开发者心中的新宠。
本文将带你从零开始,掌握如何在 Next.js 项目中配置 Drizzle,并熟练进行增删改查操作。
🏗️ 第一步:构建数据库连接单例
在开始写业务代码之前,我们需要建立一个数据库连接。在 Next.js 的开发环境中,由于热更新机制,如果每次请求都新建连接,很容易导致连接数耗尽。因此,我们需要使用全局单例模式 来管理 db 实例。
文件路径: src/db/index.ts
typescript
import { drizzle } from 'drizzle-orm/postgres-js';
import postgres from 'postgres';
import * as schema from './schema'; // 引入你的表结构定义
// 1. 获取连接字符串
const connectionString = process.env.DATABASE_URL!;
// 2. 创建 postgres 客户端
// 注意:在生产环境建议使用连接池配置,开发环境这样写即可
const client = postgres(connectionString);
// 3. 导出 db 实例
// 这个 `db` 对象就是我们在 API 或组件中用来操作数据库的核心工具
export const db = drizzle(client, { schema });
💡 核心提示: 这个
db对象封装了连接池和 SQL 构建器。只要在任何文件中import { db } from '@/db',你就拥有了操作数据库的能力。
📚 第二步:掌握核心增删改查
Drizzle 的语法设计哲学是 "像写 SQL 一样写 TypeScript"。下面我们将通过具体的代码示例,解析最常用的四种操作。
1. 增:插入数据
对应 SQL:INSERT INTO users (name, email) VALUES (...) RETURNING *;
使用 .values() 传入数据对象,配合 .returning() 可以直接拿到插入后的完整数据(包含自增 ID)。
typescript
import { db } from '@/db';
import { users } from '@/db/schema';
async function createUser() {
const newUser = await db.insert(users).values({
name: "Iron Man",
email: "ironman@avengers.com"
}).returning();
console.log("插入成功:", newUser[0]);
}
2. 删:删除数据
对应 SQL:DELETE FROM users WHERE id = 1;
删除操作必须配合 .where() 使用,否则会导致全表数据被清空(删库跑路警告⚠️)。我们需要引入 eq 函数来构建等值条件。
typescript
import { eq } from 'drizzle-orm';
async function deleteUser(userId: number) {
await db.delete(users).where(eq(users.id, userId));
console.log("删除成功");
}
3. 改:更新数据
对应 SQL:UPDATE users SET name = 'Captain America' WHERE id = 1;
使用 .set() 指定要修改的字段,同样需要配合 .where() 定位数据。
typescript
import { eq } from 'drizzle-orm';
async function updateUser(userId: number) {
await db.update(users)
.set({ name: "Captain America" })
.where(eq(users.id, userId));
console.log("更新成功");
}
4. 查:查询数据
这是最灵活的部分,Drizzle 提供了链式调用来构建复杂的查询语句。
基础查询:
typescript
// SELECT * FROM users;
const allUsers = await db.select().from(users);
条件查询:
引入 eq (等于), gt (大于), like (模糊) 等辅助函数。
typescript
import { eq, gt, and, like } from 'drizzle-orm';
// SELECT * FROM users WHERE id = 1;
const user = await db.select().from(users).where(eq(users.id, 1));
// 复杂条件:SELECT * FROM users WHERE age > 18 AND name LIKE '%Stark%';
const adults = await db.select()
.from(users)
.where(and(gt(users.age, 18), like(users.name, '%Stark%')));
指定字段查询:
typescript
// SELECT name, email FROM users;
const names = await db.select({
name: users.name,
email: users.email
}).from(users);
🔗 第三步:进阶关联查询
Drizzle 最强大的地方在于类型安全的关联查询。假设你有 users 表和 posts 表,想要查出用户及其文章,可以使用 .leftJoin()。
typescript
// SELECT * FROM users LEFT JOIN posts ON users.id = posts.userId;
const result = await db.select()
.from(users)
.leftJoin(posts, eq(users.id, posts.userId));
// result 的类型会被自动推断为:
// { users: User, posts: Post | null }[]
🛠️ 第四步:Drizzle Kit 命令行工具
除了代码层面的操作,你还需要掌握 Drizzle 的命令行工具来管理数据库结构。
| 命令 | 作用 | 对应 SQL 概念 |
|---|---|---|
npx drizzle-kit generate |
扫描 schema.ts,生成迁移文件 |
生成 CREATE TABLE... 等 SQL 脚本 |
npx drizzle-kit migrate |
执行迁移文件,同步到数据库 | 执行 SQL 脚本 |
npx drizzle-kit studio |
启动可视化界面 | 类似 pgAdmin 的轻量版 |
📌 总结
学习 Drizzle 其实就是掌握以下三件事:
- 来源 :如何从
src/db/index.ts导出db实例。 - 语法 :
db.select(),db.insert(),db.update(),db.delete()配合.where()和.values()。 - 工具 :使用
drizzle-kit同步数据库结构。