Drizzle ORM上手指南:在Next.js中优雅地操作PostgreSQL

前言

在现代 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 其实就是掌握以下三件事:

  1. 来源 :如何从 src/db/index.ts 导出 db 实例。
  2. 语法db.select(), db.insert(), db.update(), db.delete() 配合 .where().values()
  3. 工具 :使用 drizzle-kit 同步数据库结构。
相关推荐
Sylvia-girl2 小时前
c语言-2-数据类型和变量
c语言·开发语言
白露与泡影2 小时前
金三银四高频 Java 面试题及答案整理 (建议收藏)
java·开发语言
小杍随笔2 小时前
【Rust 半小时速成(2024 Edition 更新版)】
开发语言·后端·rust
GISBox3 小时前
PostGIS数据通过GISBox发布WFS/WMS全攻略
数据库·postgresql·wms·gis·postgis·矢量·gisbox
REDcker3 小时前
ARMv8、AArch64 与 arm64:命名与体系结构要点
开发语言·c++·arm
LXXgalaxy3 小时前
Uni-app 小程序页面跳转带参实战笔记(含对象传参与防坑)
开发语言·前端·javascript
oi..3 小时前
Flag和JavaScript document有关
开发语言·前端·javascript·经验分享·笔记·安全·网络安全
ZTLJQ3 小时前
数据的另一面:Python中NoSQL数据库完全解析
开发语言·python·nosql
烧饼Fighting3 小时前
java+vue推rtsp流实现视频播放(由javacv+ffmpg转为vlcj)
java·开发语言·音视频