1. MySQL (mysql2)
mysql2 是 Node.js 中性能最好的 MySQL 驱动,内置 Promise 支持和 TypeScript 类型。
npm install mysql2
import mysql, { RowDataPacket, ResultSetHeader } from "mysql2/promise";
// 创建连接池(推荐)
const pool = mysql.createPool({
host: "localhost",
user: "root",
password: process.env.DB_PASSWORD,
database: "myapp",
waitForConnections: true,
connectionLimit: 10,
});
// 查询 —— 使用参数化防止 SQL 注入
interface User extends RowDataPacket {
id: number;
name: string;
email: string;
}
const [users] = await pool.query<User[]>(
"SELECT * FROM users WHERE name LIKE ?",
["%张%"]
);
// 插入
const [result] = await pool.execute<ResultSetHeader>(
"INSERT INTO users (name, email) VALUES (?, ?)",
["李明", "liming@example.com"]
);
console.log("新用户 ID:", result.insertId);
// 事务
const conn = await pool.getConnection();
try {
await conn.beginTransaction();
await conn.execute("UPDATE accounts SET balance = balance - ? WHERE id = ?", [100, 1]);
await conn.execute("UPDATE accounts SET balance = balance + ? WHERE id = ?", [100, 2]);
await conn.commit();
} catch (e) {
await conn.rollback();
throw e;
} finally {
conn.release();
}
2. PostgreSQL (pg)
PostgreSQL 使用 pg 库,API 风格与 mysql2 类似。
npm install pg
npm install -D @types/pg
import { Pool, QueryResult } from "pg";
const pool = new Pool({
host: "localhost",
port: 5432,
user: "postgres",
password: process.env.PG_PASSWORD,
database: "myapp",
max: 10,
});
interface Product {
id: number;
name: string;
price: number;
}
// 参数化查询:$1, $2 占位符
const res: QueryResult<Product> = await pool.query(
"SELECT * FROM products WHERE price > $1 ORDER BY price DESC LIMIT $2",
[100, 20]
);
for (const row of res.rows) {
console.log(`${row.name}: ¥${row.price}`);
}
🔄 mysql2 vs pg:mysql2 用
? 占位符,pg 用 $1, $2 编号占位符。两者都支持连接池和 Promise,API 设计非常相似。
3. MongoDB (mongoose)
Mongoose 是 MongoDB 的 ODM(对象文档映射),提供 Schema 验证和类型安全。
npm install mongoose
import mongoose, { Schema, Document } from "mongoose";
// 连接
await mongoose.connect("mongodb://localhost:27017/myapp");
// 定义接口 + Schema
interface IArticle extends Document {
title: string;
content: string;
tags: string[];
createdAt: Date;
}
const articleSchema = new Schema<IArticle>({
title: { type: String, required: true },
content: { type: String, required: true },
tags: { type: [String], default: [] },
createdAt: { type: Date, default: Date.now },
});
const Article = mongoose.model<IArticle>("Article", articleSchema);
// CRUD 操作
const doc = await Article.create({
title: "TypeScript 入门",
content: "...",
tags: ["typescript", "tutorial"],
});
const articles = await Article.find({ tags: "typescript" }).sort({ createdAt: -1 }).limit(10);
await Article.updateOne({ _id: doc._id }, { $set: { title: "TS 进阶" } });
await Article.deleteOne({ _id: doc._id });
4. SQLite (better-sqlite3)
SQLite 是轻量级嵌入式数据库,适合本地工具、小型应用、测试场景。better-sqlite3 提供同步 API,性能优秀。
npm install better-sqlite3
npm install -D @types/better-sqlite3
import Database from "better-sqlite3";
const db = new Database("app.db");
// 建表
db.exec(`
CREATE TABLE IF NOT EXISTS notes (
id INTEGER PRIMARY KEY AUTOINCREMENT,
title TEXT NOT NULL,
body TEXT,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP
)
`);
// 插入(预编译语句)
const insert = db.prepare("INSERT INTO notes (title, body) VALUES (?, ?)");
insert.run("会议纪要", "讨论了 Q4 目标...");
// 查询
interface Note { id: number; title: string; body: string; created_at: string; }
const notes = db.prepare("SELECT * FROM notes ORDER BY id DESC").all() as Note[];
db.close();
5. Prisma ORM
Prisma 是现代 TypeScript ORM,最大优势是从 Schema 自动生成类型安全的客户端代码。
npm install prisma @prisma/client
npx prisma init
定义 prisma/schema.prisma:
// schema.prisma 文件内容(非 TS,但用 TS 高亮展示结构)
// datasource db { provider = "postgresql" url = env("DATABASE_URL") }
// model User {
// id Int @id @default(autoincrement())
// email String @unique
// name String?
// posts Post[]
// }
// model Post {
// id Int @id @default(autoincrement())
// title String
// author User @relation(fields: [authorId], references: [id])
// authorId Int
// }
npx prisma migrate dev --name init # 生成迁移并执行
npx prisma generate # 生成类型安全的客户端
import { PrismaClient } from "@prisma/client";
const prisma = new PrismaClient();
// 所有操作都有完整类型提示
const user = await prisma.user.create({
data: { email: "alice@example.com", name: "Alice" },
});
const usersWithPosts = await prisma.user.findMany({
include: { posts: true },
where: { email: { contains: "example" } },
});
await prisma.$disconnect();
6. 最佳实践
使用连接池
避免为每个请求创建新连接,设定合理的 connectionLimit
参数化查询
永远不要拼接 SQL 字符串,用 ? 或 $1 占位符
凭据放环境变量
数据库密码通过 process.env 读取,不要硬编码
优雅关闭连接
在 process.on("SIGTERM") 中关闭数据库连接池
// 优雅关闭示例
process.on("SIGTERM", async () => {
console.log("正在关闭数据库连接...");
await pool.end(); // mysql2 / pg
await prisma.$disconnect(); // Prisma
process.exit(0);
});
📝 本章要点
mysql2 / pg 直连数据库
轻量快速,用参数化查询保安全
Mongoose 适合 MongoDB
Schema + 接口 = 类型安全的文档操作
Prisma 是现代首选 ORM
Schema 驱动,自动生成类型,迁移方便
连接池 + 环境变量 + 优雅关闭
生产环境的三个必备实践