Node系列 · ORM:Sequelize 简介

Node系列 · ORM:Sequelize 简介

ORM(Object-Relational Mapping)把"数据库表行"映射成"JS 对象",让开发者用面向对象的方式操作数据,而不必每次写 SQL。Sequelize 是 Node 生态最成熟的 ORM------本文讲清楚它的核心概念和适用边界。

一、ORM 是什么

ORM(对象关系映射)解决一个根本问题:JS 世界是对象,数据库世界是表和行------怎么让两者无缝对接?
#mermaid-svg-CYspGbXbek3VnPba{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-CYspGbXbek3VnPba .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-CYspGbXbek3VnPba .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-CYspGbXbek3VnPba .error-icon{fill:#552222;}#mermaid-svg-CYspGbXbek3VnPba .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-CYspGbXbek3VnPba .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-CYspGbXbek3VnPba .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-CYspGbXbek3VnPba .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-CYspGbXbek3VnPba .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-CYspGbXbek3VnPba .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-CYspGbXbek3VnPba .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-CYspGbXbek3VnPba .marker{fill:#333333;stroke:#333333;}#mermaid-svg-CYspGbXbek3VnPba .marker.cross{stroke:#333333;}#mermaid-svg-CYspGbXbek3VnPba svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-CYspGbXbek3VnPba p{margin:0;}#mermaid-svg-CYspGbXbek3VnPba .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-CYspGbXbek3VnPba .cluster-label text{fill:#333;}#mermaid-svg-CYspGbXbek3VnPba .cluster-label span{color:#333;}#mermaid-svg-CYspGbXbek3VnPba .cluster-label span p{background-color:transparent;}#mermaid-svg-CYspGbXbek3VnPba .label text,#mermaid-svg-CYspGbXbek3VnPba span{fill:#333;color:#333;}#mermaid-svg-CYspGbXbek3VnPba .node rect,#mermaid-svg-CYspGbXbek3VnPba .node circle,#mermaid-svg-CYspGbXbek3VnPba .node ellipse,#mermaid-svg-CYspGbXbek3VnPba .node polygon,#mermaid-svg-CYspGbXbek3VnPba .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-CYspGbXbek3VnPba .rough-node .label text,#mermaid-svg-CYspGbXbek3VnPba .node .label text,#mermaid-svg-CYspGbXbek3VnPba .image-shape .label,#mermaid-svg-CYspGbXbek3VnPba .icon-shape .label{text-anchor:middle;}#mermaid-svg-CYspGbXbek3VnPba .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-CYspGbXbek3VnPba .rough-node .label,#mermaid-svg-CYspGbXbek3VnPba .node .label,#mermaid-svg-CYspGbXbek3VnPba .image-shape .label,#mermaid-svg-CYspGbXbek3VnPba .icon-shape .label{text-align:center;}#mermaid-svg-CYspGbXbek3VnPba .node.clickable{cursor:pointer;}#mermaid-svg-CYspGbXbek3VnPba .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-CYspGbXbek3VnPba .arrowheadPath{fill:#333333;}#mermaid-svg-CYspGbXbek3VnPba .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-CYspGbXbek3VnPba .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-CYspGbXbek3VnPba .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-CYspGbXbek3VnPba .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-CYspGbXbek3VnPba .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-CYspGbXbek3VnPba .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-CYspGbXbek3VnPba .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-CYspGbXbek3VnPba .cluster text{fill:#333;}#mermaid-svg-CYspGbXbek3VnPba .cluster span{color:#333;}#mermaid-svg-CYspGbXbek3VnPba div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-CYspGbXbek3VnPba .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-CYspGbXbek3VnPba rect.text{fill:none;stroke-width:0;}#mermaid-svg-CYspGbXbek3VnPba .icon-shape,#mermaid-svg-CYspGbXbek3VnPba .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-CYspGbXbek3VnPba .icon-shape p,#mermaid-svg-CYspGbXbek3VnPba .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-CYspGbXbek3VnPba .icon-shape .label rect,#mermaid-svg-CYspGbXbek3VnPba .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-CYspGbXbek3VnPba .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-CYspGbXbek3VnPba .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-CYspGbXbek3VnPba :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 数据库世界
JS 世界
ORM 映射
user.idrow.id
user.namerow.name
user.save → INSERT
User.findAll → SELECT
const user = { id: 1, name: 'Alice' }
users 表 id=1 name='Alice'

ORM 的核心抽象:

  • 模型(Model) = 表(Table)
  • 实例(Instance) = 行(Row)
  • 属性(Attribute) = 列(Column)

二、ORM 的核心价值

价值 说明
屏蔽 SQL 不需要拼接 SQL,开发者用 JS 方法操作数据
类型映射 DataTypes.STRING / DataTypes.INTEGER 等统一类型定义
模型关联 hasMany / belongsTo 一行声明外键关系
数据迁移 通过 migrations 管理 schema 变更
数据库无关 同一份代码可以切换 MySQL / PostgreSQL / SQLite

三、Node 中的 ORM 选项

ORM 风格 适用
Sequelize Promise / 类模型 JS 项目首选
Sequelize(TS) 同上 + 类型 TS 项目
TypeORM 装饰器(TS) TS 项目
Prisma Schema 文件 + 生成 TS 项目,现代推荐
Knex Query Builder(半 ORM) 需要手写 SQL 的场景
Drizzle TS 类型安全 + 轻量 ORM 新兴

::: tip

本指南聚焦 Sequelize ------它在 Node 生态中历史最久、社区最成熟、文档最完整。新项目如果想用 TS-first 体验,可以选 Prisma / Drizzle。

:::

四、安装与连接

bash 复制代码
npm install sequelize mysql2

mysql2 是 Sequelize 操作 MySQL 的底层驱动;不能少。

javascript:sequelize-connect.js 复制代码
const { Sequelize } = require('sequelize');

const sequelize = new Sequelize('myapp', 'root', 'your-password', {
  host: '127.0.0.1',
  port: 3306,
  dialect: 'mysql',                 // 数据库类型
  logging: false,                    // 设为 true 看 SQL 日志
  pool: {
    max: 10,
    min: 0,
    acquire: 30000,
    idle: 10000,
  },
});

// 测试连接
await sequelize.authenticate();
console.log('连接成功');

支持的 dialect:

  • mysql / mariadb
  • postgres
  • sqlite / mssql
  • db2 / oracle

五、核心概念

5.1 DataTypes

Sequelize 用 DataTypes 描述列类型:

javascript:sequelize-connect.js 复制代码
const { DataTypes } = require('sequelize');

const User = sequelize.define('User', {
  id:        { type: DataTypes.INTEGER, primaryKey: true, autoIncrement: true },
  name:      { type: DataTypes.STRING(50), allowNull: false },
  email:     { type: DataTypes.STRING(100), allowNull: false, unique: true },
  age:       { type: DataTypes.INTEGER, defaultValue: 0 },
  isActive:  { type: DataTypes.BOOLEAN, defaultValue: true },
  bio:       { type: DataTypes.TEXT },
  birthDate: { type: DataTypes.DATEONLY },
  metadata:  { type: DataTypes.JSON },
});
DataTypes 对应 MySQL
STRING VARCHAR(255)
TEXT TEXT
INTEGER INT
BIGINT BIGINT
FLOAT / DOUBLE FLOAT / DOUBLE
DECIMAL(p, s) DECIMAL
BOOLEAN TINYINT(1)
DATE DATETIME
DATEONLY DATE
JSON JSON
UUID CHAR(36)

5.2 Model(模型)

模型 = 表的抽象。每个 sequelize.define() 返回一个 Model 类。

javascript:sequelize-query.js 复制代码
const User = sequelize.define('User', { /* columns */ });

// 默认表名是 model 名复数(User → users)
// 可显式指定:tableName: 'my_users'

5.3 Instance(实例)

实例 = 一行数据。Model.create() 返回 Instance,Model.findOne() 等也返回 Instance:

javascript:sequelize-query.js 复制代码
const user = await User.create({
  name: 'Alice',
  email: 'alice@example.com',
});

// 实例属性就是行字段
console.log(user.id, user.name, user.email);

// 修改并保存
user.name = 'Alice2';
await user.save();

// 删除
await user.destroy();

5.4 查询接口

javascript:sequelize-query.js 复制代码
const { Op } = require('sequelize');

// 查询一条
const user = await User.findOne({ where: { id: 1 } });

// 按主键查
const user = await User.findByPk(1);

// 查询多条
const users = await User.findAll({
  where: { isActive: true },
  order: [['id', 'DESC']],
  limit: 10,
});

// 计数
const count = await User.count({ where: { age: { [Op.gt]: 18 } } });

六、ORM 与原始 SQL 的取舍

维度 原始 SQL(mysql2) ORM(Sequelize)
性能 最优(无中间层) 略低(多了对象转换)
可读性 复杂 JOIN 易乱 模型方法直观
类型安全 字符串 SQL,无类型 TS 项目类型完整
迁移 自己管 有 migrations 工具
跨数据库 锁死 MySQL 方言 一份代码换 PG/SQLite
复杂查询 任意 SQL 部分场景要 raw SQL
学习成本 会 SQL 即可 概念多,模型 + 关联 + 迁移

::: tip

ORM 不万能 。遇到特别复杂的报表查询(多层嵌套、子查询、窗口函数),直接 sequelize.query(sql, { type: SELECT }) 跑 raw SQL 更简单。

:::

七、连接管理

javascript:sequelize-manage.js 复制代码
// 应用退出时关闭连接
process.on('SIGTERM', async () => {
  await sequelize.close();
  process.exit(0);
});

不关连接会让 MySQL 的 Sleep 连接堆积,触发 Too many connections

八、小结

  • ORM 把"表 → 模型 / 行 → 实例 / 列 → 属性",让 JS 开发者用面向对象方式操作数据
  • Sequelize 是 Node 生态最成熟的 ORM;新项目首选,TS 项目可考虑 Prisma
  • 核心概念:DataTypes(类型)、Model(表)、Instance(行)、sequelize.query()(底层 SQL 入口)
  • 永远用占位符或 ORM API,不要拼 SQL
  • 复杂查询可以用 sequelize.query() 跑 raw SQL,不被 ORM 束缚
  • 应用退出时 sequelize.close() 释放连接
相关推荐
鸽芷咕1 小时前
达梦VS金仓选型实录:别只比TPC-C,迁移工具链才是项目成败的关键
数据库
水獭比特1 小时前
工具都批准了,为什么还不能执行?给 Agent 补上第二道校验
javascript·人工智能·node.js
AskHarries2 小时前
OpenClaw 如何查看历史对话和响应时间?
后端
n8n2 小时前
Spring Boot 3.2+ 新特性、Spring AI 核心架构与 API Key 安全管理技术文档
后端
fireworks992 小时前
接口鉴权(401与403)
java·后端
King of fraud2 小时前
Linux 下 MySQL 基础操作:创建用户、数据库与权限管理实战
linux·数据库·mysql
n8n2 小时前
Java 21 虚拟线程(Virtual Threads)
后端
努力的小雨2 小时前
sys_basebackup 适合什么场景,先看恢复目标
数据库
Csvn2 小时前
🐍 Day 5: Python 函数详解 — 参数、作用域与一等公民
人工智能·后端