Sequelize ORM 入门:Node.js 中的 SQL 操作

FreeGuideOnline 最新 2026-06-15

什么是 Sequelize ORM?

Sequelize 是一款基于 Promise 的 Node.js ORM(对象关系映射)工具,支持 PostgreSQL、MySQL、MariaDB、SQLite 以及 Microsoft SQL Server。它让你能够用 JavaScript 对象的方式操作关系型数据库,从而避免手写大量 SQL 语句。对于初学者,Sequelize 可以显著降低数据库操作的门槛,提供模型定义、关联、事务、数据校验和迁移等完整功能。

为什么选择 Sequelize?

  • 多数据库支持:一套代码即可切换不同数据库后端。
  • 模型驱动的开发:通过定义模型来映射数据库表,结构清晰。
  • 关联管理:简化表之间的关系处理(一对一、一对多、多对多)。
  • 内置校验与钩子:支持字段验证、生命周期钩子(如 beforeCreate、afterDestroy)。
  • 迁移系统:版本化管理数据库结构变更,便于团队协作。
  • 活跃社区:文档完善、生态扩展丰富(如 sequelize-typescript、sequelize-cli)。

环境准备与安装

在开始之前,确保已安装 Node.js (≥ v14) 和 npm/yarn,以及你选择的数据库(例如本地运行的 MySQL)。

创建项目并安装依赖

mkdir sequelize-demo && cd sequelize-demo
npm init -y
npm install sequelize

根据你使用的数据库,还需安装对应的数据库驱动:

  • MySQL/MariaDB: npm install mysql2
  • PostgreSQL: npm install pg pg-hstore
  • SQLite: npm install sqlite3
  • MSSQL: npm install tedious

本教程以 MySQL 为例,同时安装 mysql2

快速连接到数据库

创建 db.js 文件,配置 Sequelize 实例。

// db.js
const { Sequelize } = require('sequelize');

const sequelize = new Sequelize('database_name', 'username', 'password', {
  host: 'localhost',
  dialect: 'mysql', // 或 'postgres', 'sqlite', 'mssql'
  logging: false,   // 关闭 SQL 日志输出,可在调试时设为 console.log
});

module.exports = sequelize;

测试连接

// test-connection.js
const sequelize = require('./db');

(async () => {
  try {
    await sequelize.authenticate();
    console.log('数据库连接成功');
  } catch (error) {
    console.error('连接失败:', error);
  }
})();

运行 node test-connection.js,若输出“数据库连接成功”则配置正确。

定义模型 (Model)

模型是与数据库表对应的抽象。Sequelize 提供两种定义方式:调用 sequelize.define 或继承 Model 类。推荐使用更现代的类继承方式。

使用类继承定义模型

以简单的“用户”表为例:

// models/User.js
const { DataTypes, Model } = require('sequelize');
const sequelize = require('../db');

class User extends Model {}

User.init({
  id: {
    type: DataTypes.INTEGER,
    primaryKey: true,
    autoIncrement: true,
  },
  name: {
    type: DataTypes.STRING(100),
    allowNull: false,
    validate: {
      notEmpty: true, // 不允许空字符串
    },
  },
  email: {
    type: DataTypes.STRING(100),
    allowNull: false,
    unique: true,
    validate: {
      isEmail: true, // 内建 Email 校验
    },
  },
  age: {
    type: DataTypes.INTEGER,
    validate: {
      min: 0,
      max: 150,
    },
  },
}, {
  sequelize,           // 传入连接实例
  modelName: 'User',   // 模型名称
  tableName: 'users',  // 数据库表名(可选,默认为模型名的复数形式)
  timestamps: true,    // 自动添加 createdAt 和 updatedAt
});

module.exports = User;

同步模型到数据库

在应用中调用 sequelize.sync() 可自动创建表(开发环境使用,生产环境推荐迁移)。

// app.js
const sequelize = require('./db');
const User = require('./models/User');

(async () => {
  await sequelize.sync({ force: false }); // force: true 会先删除表再重建
  console.log('所有模型已同步');
})();

CRUD 基础操作

创建记录 (Create)

const newUser = await User.create({
  name: '张三',
  email: 'zhangsan@example.com',
  age: 28
});
console.log(newUser.toJSON()); // 输出新用户数据

查询记录 (Read)

// 查询所有用户
const allUsers = await User.findAll();

// 按条件查询单条
const user = await User.findOne({ where: { email: 'zhangsan@example.com' } });

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

// 使用特定字段过滤和排序
const filteredUsers = await User.findAll({
  where: { age: { [Op.gt]: 20 } }, // 年龄大于 20 需导入 Op
  order: [['name', 'ASC']],
  limit: 5,
});

别忘了导入 Op 用于高级操作符:

const { Op } = require('sequelize');

常用操作符:[Op.gt] (大于), [Op.lt] (小于), [Op.like] (模糊), [Op.in] (包含) 等。

更新记录 (Update)

// 更新单个字段
await User.update({ age: 29 }, { where: { id: 1 } });

// 通过实例更新(推荐,会触发钩子和校验)
const user = await User.findByPk(1);
if (user) {
  user.age = 30;
  await user.save();
}

删除记录 (Delete)

// 直接删除
await User.destroy({ where: { id: 1 } });

// 或通过实例
const user = await User.findByPk(2);
if (user) await user.destroy();

模型关联 (Associations)

Sequelize 提供四种关联类型:HasOneBelongsToHasManyBelongsToMany

一对一 (One-to-One)

假设每个用户对应一个个人资料 (Profile):

// models/Profile.js
class Profile extends Model {}
Profile.init({
  bio: DataTypes.TEXT,
  avatar: DataTypes.STRING,
}, { sequelize, modelName: 'Profile' });

// 定义关联
User.hasOne(Profile, { foreignKey: 'userId' });
Profile.belongsTo(User, { foreignKey: 'userId' });

查询时包含关联数据:

const userWithProfile = await User.findByPk(1, {
  include: Profile
});

一对多 (One-to-Many)

用户与文章 (Post) 的关系:

User.hasMany(Post, { foreignKey: 'userId' });
Post.belongsTo(User, { foreignKey: 'userId' });

获取用户的所有文章:

const user = await User.findByPk(1, { include: Post });
console.log(user.Posts); // 别名默认大写,可通过 as 设置

多对多 (Many-to-Many)

用户与角色 (Role) 通过中间表 user_roles 关联:

User.belongsToMany(Role, { through: 'user_roles' });
Role.belongsToMany(User, { through: 'user_roles' });

添加关联:user.addRole(role),查询关联:user.getRoles()

使用迁移 (Migrations)

迁移用于版本化数据库结构变更,适合团队协作和生产环境。使用 sequelize-cli 工具管理。

安装与初始化

npm install --save-dev sequelize-cli
npx sequelize-cli init

初始化后会生成 configmodelsmigrationsseeders 目录。

配置数据库连接

编辑 config/config.json,配置不同环境(development, test, production)的数据库信息。

创建迁移文件

npx sequelize-cli migration:generate --name create-users-table

在生成的迁移文件中编写“升级”和“降级”逻辑:

module.exports = {
  up: async (queryInterface, Sequelize) => {
    await queryInterface.createTable('users', {
      id: {
        type: Sequelize.INTEGER,
        primaryKey: true,
        autoIncrement: true
      },
      name: Sequelize.STRING,
      email: Sequelize.STRING,
      createdAt: Sequelize.DATE,
      updatedAt: Sequelize.DATE
    });
  },
  down: async (queryInterface) => {
    await queryInterface.dropTable('users');
  }
};

执行迁移

npx sequelize-cli db:migrate

回滚上一次迁移:npx sequelize-cli db:migrate:undo

实用技巧与常见问题

数据校验

Sequelize 允许在模型定义中配置校验,也可自定义校验器:

email: {
  type: DataTypes.STRING,
  validate: {
    isEmail: true,
    myCustomValidator(value) {
      if (!value.endsWith('@company.com')) {
        throw new Error('必须使用公司邮箱');
      }
    }
  }
}

钩子 (Hooks)

在数据生命周期不同阶段自动执行逻辑,例如密码加密:

User.addHook('beforeCreate', async (user) => {
  user.password = await hashPassword(user.password);
});

事务 (Transactions)

保证多个操作原子性:

const t = await sequelize.transaction();
try {
  const user = await User.create({ name: '李四' }, { transaction: t });
  await user.createProfile({ bio: 'hello' }, { transaction: t });
  await t.commit();
} catch (error) {
  await t.rollback();
}

原始查询与复杂查询

偶尔需要手写 SQL,可使用 sequelize.query

const [results, metadata] = await sequelize.query(
  'SELECT * FROM users WHERE age > :age',
  {
    replacements: { age: 25 },
    type: QueryTypes.SELECT
  }
);

也可利用 Sequelize 的 literal 或聚合函数如 fncol 构建复杂查询。

总结

本教程带你从零搭建了 Sequelize ORM 的开发环境,涵盖了连接数据库、定义模型、CRUD 操作、关联关系以及迁移系统的使用。通过 ORM,你可以用更符合 JavaScript 习惯的方式管理数据库逻辑,显著提升开发效率和可维护性。作为下一步,建议深入学习 Sequelize 的查询作用域 (Scopes)、多态关联、性能优化以及结合 Express 构建完整的 RESTful API。

祝你写码愉快!