設置 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 的開發者來說會非常上手。