了解Node.js Sequelize ORM模型

246 阅读9分钟

了解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自动创建两个新列,命名为createdAtupdatedAt 。这两列存储了时间戳,分别显示一条记录的创建和更新时间。

生产中的同步可能是破坏性的,不推荐。只在开发层面上使用同步化。在生产中,用[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);

UserPost 模型中定义外键,如下面的代码片断所示。

//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"
    }

点击发送来运行请求。检查响应。预期的响应如下面的屏幕截图所示。

Postman create user request

获取用户

我们将创建一个端点,从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响应。

users

编辑用户

我们将创建一个端点来更新用户的详细信息。该端点接收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"
    }

点击发送来运行请求。检查响应。预期的响应如下面的屏幕截图所示。

Postman edit user

创建帖子

我们将创建一个端点,将新的帖子插入到数据库中。该端点接收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"
    }

点击发送来运行请求。检查响应。预期的响应如下面的屏幕截图所示。

Postman create post

获取帖子

我们将创建一个端点,从帖子表中返回帖子。在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响应。

Postman get posts

删除用户

我们将创建一个端点,从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末尾的数字代表要删除的记录的主键。

Postman delete user

总结

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