基于 Node.js 的 ORM(对象关系映射)工具——Sequelize介绍与使用,并举案例分析
便捷性介绍
支持多种数据库,包括 PostgreSQL、MySQL、MariaDB、SQLite 和 Microsoft SQL Server。Sequelize 提供了丰富的功能,帮助开发者用 JavaScript(或 TypeScript)代码操作数据库,而无需直接书写 SQL 语句。
Sequelize 的主要特点
跨数据库支持:支持主流数据库如 MySQL、PostgreSQL、SQLite 等。
模型(Model)定义:通过定义模型(类似于类),对应数据库的表。
迁移(Migrations)工具:方便管理数据库的版本变化。
事务支持:提供事务操作,确保数据一致性。
查询生成器:支持链式查询和条件查询,生成高效的 SQL 语句。
钩子(Hooks):支持生命周期钩子,方便在特定操作前后执行代码。
基本使用介绍
安装 Sequelize 和数据库驱动
npm install sequelize
npm install mysql2 # 对于 MySQL
创建实例
const { Sequelize } = require('sequelize');
// 创建与数据库的连接实例
const sequelize = new Sequelize('database_name', 'username', 'password', {
host: 'localhost',
dialect: 'mysql', // 数据库类型,可更换为 'postgres', 'sqlite', 'mssql' 等
logging: false, // 是否打印 SQL 日志
});
同步模型到数据库
将模型与数据库表同步
(async () => {
try {
await sequelize.authenticate(); // 验证连接是否成功
console.log('连接建立成功');
await sequelize.sync({ force: true }); // 同步模型,`force: true` 表示重建表
console.log('所有异步模型成功.');
} catch (error) {
console.error('不能连接到数据库', error);
} finally {
await sequelize.close(); // 关闭数据库连接
}
})();
定义模型:(相当于是在建数据表)
模型是 Sequelize 的核心,用来描述数据库的表结构
const { DataTypes } = require('sequelize');
const User = sequelize.define('User', {
id: {
type: DataTypes.INTEGER,
autoIncrement: true,
primaryKey: true,
},
username: {
type: DataTypes.STRING,
allowNull: false,
},
email: {
type: DataTypes.STRING,
unique: true,
},
password: {
type: DataTypes.STRING,
},
}, {
tableName: 'users', // 指定表名
timestamps: true, // 是否自动生成 createdAt 和 updatedAt 字段
});
数据操作(增删改查)
//创建数据
const newUser = await User.create({
username: 'JohnDoe',
email: 'johndoe@example.com',
password: '123456',
});
console.log(newUser.toJSON());
// 查询所有用户
const users = await User.findAll();
console.log(users);
// 按条件查询
const specificUser = await User.findOne({ where: { username: 'JohnDoe' } });
console.log(specificUser);
//更新数据
await User.update({ email: 'newemail@example.com' }, {
where: { username: 'JohnDoe' },
});
//删除数据
await User.destroy({
where: { username: 'JohnDoe' },
});
其他基本数据库操作
关联(Associations)
Sequelize 支持表之间的关系:一对一 (1:1)、一对多 (1:N)、多对多 (N:M)。
const Post = sequelize.define('Post', { title: DataTypes.STRING });
User.hasMany(Post); // 一个用户有多个帖子
Post.belongsTo(User); // 一个帖子属于一个用户
事务(Transactions)
const t = await sequelize.transaction();
try {
const user = await User.create({ username: 'Jane' }, { transaction: t });
await t.commit(); // 提交事务
} catch (error) {
await t.rollback(); // 回滚事务
}
生命周期钩子(Hooks)
User.beforeCreate((user, options) => {
console.log('Before creating user:', user.username);
});
原生查询
如果需要执行原生 SQL,可以使用 sequelize.query。
const [results, metadata] = await sequelize.query('SELECT * FROM users');
具体项目案例
现在要实现一个用户认证模块,以node为后端,数据库是确定的,但是不在数据库当中建任何表,全依靠Sequelize进行:
src/config/db.js(后端数据库连接)
const { Sequelize } = require('sequelize')
// 使用 Sequelize 连接 MySQL
// 这里配置数据库名称、用户名、密码、主机和方言
const sequelize = new Sequelize('project', 'root', '123456', {
host: 'localhost',
dialect: 'mysql',
})
/**
* 连接数据库的异步函数
* 尝试验证与数据库的连接,如果成功则打印确认消息
* 如果连接失败,则打印错误消息并退出进程
*/
const connectDB =
async () => {
try {
await sequelize.authenticate()
console.log('MySQL Connected')
} catch (err) {
console.error('Unable to connect to the database:', err.message)
process.exit(1)
}
}
// 导出 sequelize 实例和 connectDB 函数供外部使用
module.exports = { sequelize, connectDB }
src/modules/User.js(用户模型-用户数据表定义建立)
const { Sequelize, DataTypes } = require('sequelize')
const bcrypt = require('bcrypt')
const { sequelize } = require('../config/db')
// 定义 User 模型
const User = sequelize.define('User', {
username: {
type: DataTypes.STRING,
allowNull: false,
unique: true,
},
password: {
type: DataTypes.STRING,
allowNull: false,
},
})
// 在保存用户之前加密密码
User.beforeCreate(async (user) => {
user.password = await bcrypt.hash(user.password, 10)
})
module.exports = User
src/app.js(程序入口)
//dotenv 是一个用于 加载环境变量 的 Node.js 模块,它会从项目根目录的 .env 文件中读取环境变量,并将其添加到 process.env 对象中
//开发者就可以通过 process.env.变量名 来访问环境变量。
require('dotenv').config()
const express = require('express')
//---------------------数据库部分-------------------------------------------------------------------------------
const { connectDB, sequelize } = require('./config/db')
const app = express()
// 初始化数据库连接
connectDB()
// 同步数据库表结构,sequelize.sync 会同步模型与数据库表。alter: true 会根据模型的定义修改数据库表结构(谨慎使用于生产环境)。
sequelize.sync({ alter: true }).then(() => {
console.log('数据库和表结构已经同步成功')
})
//---------------------------------------------------------------------------------------------------------------
//express.json() 是一个中间件,用于解析 JSON 格式的请求体。
app.use(express.json())
//通过 process.env.PORT 读取 .env 文件中配置的端口号,如果未定义,则默认使用 5000
const PORT = process.env.PORT || 5000
app.listen(PORT, () => console.log(`Server running on port ${PORT}`))
// app.use('/api/auth', authRoutes):当访问 /api/auth 路径时,将由 authRoutes 处理请求。
// 这是模块化路由的常见实现方式。
const authRoutes = require('./routes/authRoutes')
app.use('/api/auth', authRoutes)
其他一些可能用得上的功能
支持原始 SQL 查询
const results = await sequelize.query('SELECT * FROM Users WHERE username = :username', {
replacements: { username: 'JohnDoe' },
type: QueryTypes.SELECT,
});
高级查询
条件查询
const users = await User.findAll({
where: {
username: {
[Op.like]: 'J%',
},
},
});
分页与排序
const users = await User.findAll({ limit: 10, offset: 20, order: [['username', 'ASC']] });
还有数据迁移和数据库连接池此处就不讲了
此处提供:
官方文档: https://sequelize.org/
GitHub 仓库: https://github.com/sequelize/sequelize
Sequelize 是一个功能全面的 ORM 工具,它简化了数据库操作,支持多种数据库类型。通过模型定义、查询构建、事务管理和数据库迁移,开发者可以高效地处理复杂的数据管理需求。如果你的项目需要频繁的数据库操作或希望避免直接使用 SQL,Sequelize 是一个值得选择的解决方案。