了解Node.js的Sequelize ORM模型
Sequelize是一个用于Node.js的对象关系映射器。Sequelize让我们可以连接到数据库并执行操作,而无需编写原始的SQL查询。它抽象了SQL查询,使我们更容易与数据库模型作为对象进行交互。
这篇文章将帮助你了解Sequelize模型,从模型定义到模型使用。Sequelize与所有基于SQL的数据库一起工作。在本教程中,我将使用MySQL。然而,你可以使用你选择的任何基于SQL的数据库。
先决条件
为了更容易跟进这篇文章,你可能需要以下条件。
- 对[Node.js]的基本了解。
- 在你的电脑上安装Node.js。
- [关系数据库管理系统(RDBMS)]方面的知识。
- 在你的电脑上安装一个基于SQL的DBMS。
- Sequelize安装和设置方面的基本知识。幸运的是,这在《[Sequelize ORM for Node.js简介]》一文中已经有所涉及。
目标
在本教程结束时,你应该能够。
- 理解不同的数据类型并在模型定义中使用它们。
- 验证模型。
- 定义模型关联。
- 在Sequelize中定义模型。
- 从Sequelize模型生成数据库模式。
Sequelize的设置
本教程假设你已经安装了Node.js、一个基于SQL的DBMS和一个代码编辑器。
通过在你的命令行上运行下面的命令来安装Sequelize。
npm install --save sequelize
为你想使用的数据库安装Sequelize数据库驱动,请运行下面的命令。
npm install --save pg pg-hstore # PostgresSQL
npm install --save mysql2 # MySQL
npm install --save tedious # MS SQL
安装npm包Sequelize-CLI。
npm install - g sequelize-cli
创建一个项目文件夹。在你的项目文件夹路径中,运行下面的命令,在该文件夹中初始化Sequelize。
sequelize init
上述命令创建了以下文件夹。
config:一个包含配置文件的文件夹migrations: 一个包含所有迁移文件的文件夹models: 一个包含项目所有模型的文件夹seeders: 一个存放所有种子文件的文件夹
所有Sequelize-CLI命令都应该在项目文件夹中运行。
数据库连接
导航到先前生成的config 文件夹下的config.json 文件,以连接到数据库。这个文件保存了开发、测试和生产数据库的数据库连接。如下面的代码片断所示,编辑开发数据库连接。
"development": {
"username": "root",
"password": null, // Your password. If the password is blank, enter null.
"database": "sequelize_tutorial",
"host": "localhost",
"dialect": "mysql",
"port": 3307
}
创建数据库
我们需要创建上面数据库连接中定义的数据库。通过在命令行上运行下面的命令来创建一个数据库。你也可以直接在你的DBMS上创建数据库。
sequelize db:create
Sequelize中的模型介绍
模型是任何对象-关系映射(ORM)的骨干。因此,你必须了解如何广泛地使用模型来实现ORM的全部好处。
模型是独立于数据库的。一个模型是一个抽象,反映了数据库中的一个实体或一个表。Sequelize中的模型定义了数据库中的实体名称、实体属性以及它们的数据类型。
在本教程中,让我们考虑一个存储用户和博客文章的数据库。我们需要两个表来存储用户和帖子。实体User 和实体Post 之间将存在一对多的关系。对于本教程,我们将保持简单。
序列化数据类型
模型中的每个属性都代表数据库表中的一个列。每一列都必须有一个数据类型。下面是Sequelize中一些最常见的数据类型。
DataTypes.STRING // VARCHAR(255)
DataTypes.TEXT // Text
DataTypes.BOOLEAN // TINYINT(1)
DataTypes.INTEGER // Integer
DataTypes.FLOAT // Float
DataTypes.DOUBLE // Double
DataTypes.DECIMAL // Decimal
DataTypes.DATE // Date
DataTypes.DATEONLY // Date without time
创建数据库模型
在本教程中,我们将使用Sequelize-CLI来创建模型。在项目文件夹中的命令行上运行下面的命令来创建用户和职位模型。用你的值替换ModelName,attribute1,attribute2,attribute3, 和datatype 。
sequelize model:generate --name ModelName --attributes attribute1:datatype, attribute2:string, attribute3:datatype
上述命令将创建这些模型。migrations 文件夹和models 文件夹中的新文件被创建。要修改每个模型,按照模型名称编辑文件。
这些命令不包括属性
id,它应该是每个表的主键。该属性是自动生成的。
你可以通过编辑生成的模型文件添加更多属性,user.js, 和post.js. 默认情况下,表名与模型名相同。打开模型文件并定义表名,如下图所示。
{
sequelize,
//define table name
tableName: 'users',
modelName: 'User',
});
{
sequelize,
//define table name
tableName: 'posts',
modelName: 'Post',
});
为了在数据库中实现模型,我们需要运行Node.js应用程序。在项目根部,创建一个脚本,app.js 。我们将使用Express框架。Express是一个Node.js网络框架,用于以一种简化的方式创建服务器。在你的终端上运行下面的命令来安装Express。
npm install express --save
在脚本中添加下面的代码app.js 。
const express = require("express");
const {sequelize, User, Post} = require('./models'); // import models
const app = express(); // create a new express app
app.use(express.json());
app.get('/', function (req, res) {
res.send('App running')
});
app.listen({port: 5005}, async() =>{
await User.sync({ force: true });
});
在命令行上,运行下面的命令来启动应用程序。
node app.js
该应用程序自动连接到数据库,并将模型与数据库同步。
Sequelize自动创建两个新列,命名为createdAt 和updatedAt 。这两列存储了时间戳,分别显示一条记录的创建和更新时间。
生产中的同步可能是破坏性的,不推荐。只在开发层面上使用同步化。在生产中,用[Migrations]实现同步。
序列化模型约束和验证
约束是在SQL级别定义的数据规则。如果SQL查询不符合约束规则,数据库会抛出一个错误。Sequalize会将错误转发给JavaScript。打开user.js ,在email 属性中添加约束,如下图所示。
email:{
type:DataTypes.STRING,
unique: true,
allowNull: false
}
如果上述例子中的电子邮件为空或不唯一,数据库将抛出一个错误。
验证是由Sequelize在JavaScript级别完成的。Sequelize提供内置的验证器函数。你也可以创建你的自定义验证函数。如果只有验证通过,SQL查询将执行。下面是一些常用的Sequelize内置验证器。
isAlphanumeric: true, // checks for alphanumeric characters only
isNumeric: true, // allow numbers only
isLowercase: true, // allow lowercase only
isUppercase: true, // allow uppercase allow
打开user.js ,在email 属性上添加约束,如下图所示。注意到错误的返回信息。
email:{
type:DataTypes.STRING,
unique: true,
allowNull: false,
validate:{
isEmail: {msg: "It must be a valid Email address"},
}
}
Sequelize模型关联
在本节中,我们将在Sequelize中实现关联。Sequelize支持三种模型关联。
- 一对一
- 一对多
- 多对多
在我们之前创建的模型中,我们有一个一到多的关联。这导致了两个Sequelize关系。
User.hasMany(Post);Post.BelongsTo(User);
在User 和Post 模型中定义外键,如下面的代码片断所示。
//User Model
class User extends Model {
static associate({Post}) {
// define association here
this.hasMany(Post, {foreignKey: 'userId', as: 'posts' })
}
};
// Post Model
class Post extends Model {
static associate({User}) {
// define association here
this.belongsTo(User, {foreignKey: 'userId', as: 'user' })
}
};
应用程序测试
我们现在可以用数据测试我们的应用程序。
我们将为每个功能创建一个端点。为了实现对数据库的修改,运行应用程序。我们将不对模型做更多的修改。编辑app.js 。将这一行替换为
await sequelize.sync({force: true});
与
await sequelize.authenticate();
这将确保我们的数据库表在每次运行应用程序时不会被重新创建。
插入用户
我们将创建一个端点,将新用户插入数据库。该端点接收JSON格式的数据。在app.js 中添加下面的代码,然后运行该应用程序。
// Create new user
app.post("/users", async(req,res) =>{
const { name, email, role} = req.body
try{
const user = await User.create({name, email, role});
return res.json(user);
}catch(err){
return res.status(500).json(err);
}
});
在Postman中,创建一个POST 请求,端点位置为http://localhost:5005/users/ 。在Body部分,选择raw JSON ,并插入下面的JSON数据。
{
"name": "Benson Wyne",
"email": "Benson@mexamplemail.com",
"role": "user"
}
点击发送来运行请求。检查响应。预期的响应如下面的屏幕截图所示。

获取用户
我们将创建一个端点,从users 表中返回用户。在app.js 中添加下面的代码,并运行该应用程序。
//Fetch users
app.get("/users", async(req,res) =>{
try{
const users = await User.findAll({include:'posts'});
return res.json(users);
}catch(err){
return res.status(500).json({err: "An error occured"});
}
});
在Postman中,创建一个GET 请求,端点位置为http://localhost:5005/users/ 。你将得到一个包含数据库中所有用户的JSON响应。

编辑用户
我们将创建一个端点来更新用户的详细信息。该端点接收JSON格式的数据。在app.js 中添加下面的代码并运行该应用程序。
//Update user
app.put("/users/:id", async(req,res) =>{
const id = req.params.id;
const { name, email, role} = req.body;
try{
const user = await User.findOne({
where: {id}
});
user.name = name;
user.email = email;
user.role = role;
await user.save();
return res.json(user);
}catch(err){
return res.status(500).json({err: "An error occured"});
}
});
在Postman中,创建一个PUT 请求,端点位置为http://localhost:5005/users/1 。URL末尾的数字代表要更新的记录的主键。
在正文部分,选择raw JSON ,并插入你想对记录进行修改的JSON数据。
{
"name": "Benson Wyne",
"email": "Benson@examplemail.com",
"role": "admin"
}
点击发送来运行请求。检查响应。预期的响应如下面的屏幕截图所示。

创建帖子
我们将创建一个端点,将新的帖子插入到数据库中。该端点接收JSON格式的数据。在app.js 中添加以下代码,并运行该应用程序。
// Create new post
app.post("/posts", async(req,res) =>{
const { content, userId} = req.body
try{
const user = await User.findOne({
where: {id: userId}
});
const post = await Post.create({content, userId: user.id });
return res.json(post);
}catch(err){
return res.status(500).json(err);
}
});
在Postman中,创建一个POST 请求,端点位置为http://localhost:5005/posts/ 。在正文部分,选择raw JSON 并插入下面的JSON数据。
{
"content": "Sample post 1",
"userId": "1"
}
点击发送来运行请求。检查响应。预期的响应如下面的屏幕截图所示。

获取帖子
我们将创建一个端点,从帖子表中返回帖子。在app.js 中添加下面的代码,并运行该应用程序。
// Get posts
app.get("/posts", async(req,res) =>{
try{
const posts = await Post.findAll({include:'users'});
return res.json(posts);
}catch(err){
return res.status(500).json(err);
}
});
在Postman中,创建一个GET 请求,端点位置为http://localhost:5005/posts/ 。你将得到一个包含数据库中所有帖子的JSON响应。

删除用户
我们将创建一个端点,从users 表中删除记录。在app.js 中添加下面的代码,并运行该应用程序。
//Delete user
app.delete("/users/:id", async(req,res) =>{
const id = req.params.id;
try{
const user = await User.findOne({
where: {id}
});
await user.destroy();
return res.json({message: "User Deleted"});
}catch(err){
return res.status(500).json({err: "An error occured"});
}
});
在Postman中,创建一个DELETE 请求,端点位置为http://localhost:5005/users/5 。URL末尾的数字代表要删除的记录的主键。

总结
我们已经了解了Sequelize模型的工作原理。