设置 Drizzle ORM 连接 Postgres 为例
前言
单纯通过 SQL 与关系数据库直接沟通,可能会带来开发效率与安全性的问题,因此挑选合适的 ORM 多一层抽象是常见的选择,而 Drizzle ORM 是我最常使用也是接触 ORM 的起点。它在 TypeScript 生态中有出色支持,虽然相对新颖,但社区活跃,值得一试。
为什么选择 Drizzle ORM?
主因是相较于其他 ORM 如 Prisma 可能造成抽象泄漏的问题,Drizzle 提供了两种形式的 API 与数据库互动:
既保留了传统 ORM 易用的操作界面,也提供更接近底层运作的互动方式,某方面来说降低了学习成本也更避免技术上的锁定,身为新手也能站在适当的抽象程度上学习。
听说过吓人的故事像是 Prisma 容易产出低效的语句: Migration Lesson: Don’t Use Prisma | Prime Reacts,但由于抽象层过多,当需要处理底层问题时就显得困难,进而影响系统的扩展性与性能。Drizzle 官方有对应的 Benchmark或许能参考看看。
更多好处像是:TypeScript 支持、无任何依赖、完全支持 Serverless、支持多种数据库(如 PostgreSQL、MySQL、SQLite)与云端供应商(如 Neon、PlanetScale 等),更多能参考官方文档:Why Drizzle。
Drizzle 与 Postgres
依赖安装
假设有一个 TS 专案需要与 Postgres 沟通,先把会用到的依赖都安装上:
- dotenv - 管理环境变量
- tsx - 执行 TypeScript 文件
- node-postgres - Node.js Postgres 驱动
- @types/pg - pg TS 类型
- drizzle-orm - ORM 本身
- drizzle-kit - DB Migration 用途与附属工具
pnpm add drizzle-orm pgpnpm add -D drizzle-kit tsx @types/pg dotenv
文件结构
官方推荐文件结构如下,在 index.ts
中会使用 Drizzle 与数据库进行互动,但在这之前有许多概念与设置需要提前准备。
📦 <project root> ├ 📂 drizzle ├ 📂 src │ ├ 📂 db │ │ └ 📜 schema.ts │ └ 📜 index.ts ├ 📜 .env ├ 📜 drizzle.config.ts ├ 📜 package.json └ 📜 tsconfig.json
连接数据库
其中 .env
添加数据库的连接网址,通常是以下的格式,具体如何启动 Postgres 服务器于本地可以参考:初学 Docker 并轻松构建 Postgres。
postgresql://alex:[email protected]/dbname └──┘ └───────┘ └─────────────────────────────────────────────┘ └────┘ ʌ ʌ ʌ ʌ role -│ │ │- hostname │- database │ │- password
DATABASE_URL=
在 index.ts
使用 drizzle 选择对应的 Postgres 驱动 进行连接即可。接着执行该文件: pnpm tsx src/index.ts
便能连接上数据库。
import 'dotenv/config';import { drizzle } from 'drizzle-orm/node-postgres';
const db = drizzle(process.env.DATABASE_URL!);console.log(db)
具体来说通过 node-postgres 驱动与数据库进行沟通,可以参考官方说明:Database connection with Drizzle
Database First 与 Code First
将 Drizzle ORM 连接上 Postgres 后有两种风格的开发策略可以选择处理数据库与代码之间的映射关系:
- Database First
- Code First
这两种方法的差异在于「先定义数据库结构」还是「先撰写程序模型」,各有优缺点,适用于不同的场景。
Database First
先设计并建立好数据库,然后由 ORM 工具依据数据库结构产生对应的模型代码,适合用于:
-
有现成数据库或既有系统需要整合
-
数据库由第三方设计与维护
-
想保持数据库设计的严谨性与一致性
-
优点
- 与现有数据库整合容易
- 数据库结构清晰、可由工具产生 ER 图
- 较容易与其他非 ORM 应用共享数据库
-
缺点
- 每次数据库更改都需手动更新模型(或重新产生)
- 程序开发较依赖数据库调整的速度
Code First
先写好模型代码,然后由 ORM 工具依据代码自动建立或同步数据库结构。 适合情境:
-
新项目、从零开始
-
开发团队主导数据结构设计
-
敏捷开发,需求快速变动
-
优点
- 开发流程集中在代码,版本控制方便
- 更容易做自动化迁移(migrations)
- 不需先建数据库,即可专注于业务逻辑开发
-
缺点
- 若数据库由多人共享,结构变更需谨慎管理。
- 较不适合整合已有数据库。
Drizzle Kit 进行 Database Migration
# Drizzle kit 指令范例pnpm drizzle-kit generatepnpm drizzle-kit migratepnpm drizzle-kit pushpnpm drizzle-kit pullpnpm drizzle-kit checkpnpm drizzle-kit uppnpm drizzle-kit studio
Drizzle migrations fundamentals 列出不同情境下如何通过 drizzle-kit 工具进行同步。举例以 Code First 开发策略为例,先建立「模型代码」再同步到数据库。
定义数据库数据表及字段设计
import { integer, pgTable, varchar } from "drizzle-orm/pg-core";
export const usersTable = pgTable("users", { id: integer().primaryKey().generatedAlwaysAsIdentity(), name: varchar({ length: 255 }).notNull(), age: integer().notNull(), email: varchar({ length: 255 }).notNull().unique(),});
Drizzle Kit 设置
设置 drizzle.config.ts
供 Drizzle Kit 了解 Migration 前所需的数据。
import 'dotenv/config';import { defineConfig } from 'drizzle-kit';
export default defineConfig({ out: './drizzle', schema: './src/db/schema.ts', dialect: 'postgresql', dbCredentials: { url: process.env.DATABASE_URL!, },});
进行 Migration
# drizzle-kit push 将架构和后续架构变更直接推送到数据库,同时省略 SQL 文件生成。pnpm drizzle-kit push
观察数据库变动
Drizzle Studio 是一项还在测试中的数据库预览工具。
pnpm drizzle-kit studio
Warning Drizzle Studio is currently in Beta. If you find anything that is not working as expected or should be improved, feel free to create an issue on GitHub: https://github.com/drizzle-team/drizzle-kit-mirror/issues/new or write to us on Discord: https://discord.gg/WcRKz2FFxN
Drizzle Studio is up and running on https://local.drizzle.studio
总结
Drizzle ORM 是一个轻量、现代、并拥有良好 TypeScript 体验的 ORM 工具。无论你是喜欢高度抽象的操作方式,还是希望保有接近 SQL 的灵活性,它都能提供弹性的开发体验。
当你熟悉了基本的连接与迁移流程后,接下来只需专注于 query 与 schema 的设计,相信对熟悉 SQL 的开发者来说会非常上手。