什么是 Sequelize

我们知道 Web 应用开发中的 Web 后端开发一般都是 Java、Python、ASP.NET 等语言。十年前,Node.js 的出现使得原本仅限于运行在浏览器中的 JavaScript 也有了可以开发 Web 后端的机会了。

就对于 MySQL 来说,已经有了偏向于底层的框架 mysql npm 包,但现在要说的是一个基于 Promise 的 Node.js ORM 工具 —— Sequelize.js。结合 Express 来响应 HTTP 请求,定义路由表用于执行不同的 HTTP 请求动作,前端工程师可以基于 Node.js 开发一套服务器。

Sequelize.js 目前支持 Postgres、MySQL、MariaDB、SQLite 以及 Microsoft SQL Server。它具有强大的事务支持、关联关系、预读和延迟加载、读取复制等功能。

ORM 是对象关系映射(Object Relational Mapping)的简称,是一种程序设计技术,用于实现面向对象编程语言里不同类型系统的数据之间的转换。其实是创建了一个可在编程语言里使用的“虚拟对象数据库”。

原生 API 的问题

如果 users 和 comments 是一对多的关系。在不使用 Sequelize 框架操作数据库时,对于关联查询,是这样操作的:

let sql = "select u.*, c.u_id, c.content from users as u inner join comments as c on u.id = c.u_id"

connection.query(sql, (err, result, fields) => {
    res.send(result)
})

查询每一个用户发表的评论,所以查询的结果为:

[
    {
        "id": 1,
        "name": "Jane",
        "userId": 1,
        "content": "内容111"
    },
    {
        "id": 1,
        "name": "Jane",
        "userId": 1,
        "content": "内容222"
    },
    {
        "id": 1,
        "name": "Jane",
        "userId": 1,
        "content": "内容333"
    }
]

查询结果显示,只有 content 字段的内容不一致,但结构是重复,我们希望得到的结果是这样的:

[
    {
        "id": 1,
        "name": "Jane",
        "userId": 1,
        "content": ["内容111", "内容222", "内容333"]
    }
]

现在,是时候使用 Sequelize 来连接数据库进行操作了。

基于 Sequelize 开发接口

安装依赖

你需要保证你的项目需要有 mysql2、sequelize、express 三个依赖包,你可以选择一个干净的项目来进行实战。

npm install mysql2 express

连接数据库

导入 express、sequelize

const express = require('express')
const { Sequelize, DataTypes } = require('sequelize')

实例化 sequelize

Sequelize 类有四个构造函数,分别如下:

constructor(database: string, username: string, password?: string, options?: Options);
constructor(database: string, username: string, options?: Options);
constructor(options?: Options);
constructor(uri: string, options?: Options);

Options 定义的是一个 TS 接口,这个接口有更多的数据库配置信息,具体还有什么内容,查看源码。在这里,我选择使用第三个构造函数对数据库进行配置。

const sequelize = new Sequelize({
    database: 'test',
    username: 'shiramashiro',
    password: '123456',
    host: 'localhost',
    port: 3306,
    dialect: 'mysql' // 该字段指定要连接的数据库
})

创建数据表

定义模型

模型是 Sequelize 用于描述 JS 对象与数据库表的映射关系。

const User = sequelize.define('user', {
    username: DataTypes.TEXT,
    password: {
        type: DataTypes.STRING(11),
        defaultValue: '123456'
    }
})

const Comment = sequelize.define('comment', {
    content: DataTypes.TEXT
})

关联模型

在使用关联查询之前,需要让 Sequelize 知道数据库表之间的关系,是一对一,还是一对多,还是多对多。

Sequelize 提供了四种关联方法:HasOne 、BelongsTo 关联类型、HasMany 关联类型、BelongsToMany 关联类型。

根据当前文章案例,我需要使用 HasMay 关联类型和 BelongsTo 关联类型。

/**
 * 关联模型,一对多,User 与 Comment 是一对多的关系。
 */
User.hasMany(Comment)
Comment.belongsTo(User)

添加数据

Sequelize 为我们提供了批量添加数据的方法,即 bulkCreate 方法。


User.bulkCreate([
    {
        username: 'shiramashiro',
        password: '654321'
    },
    {
        username: 'javascript',
        password: 'js123456'
    }
])

Comment.bulkCreate([
    {
        content: '内容111',
        userId: 1
    },
    {
        content: '内容222',
        userId: 1
    },
    {
        content: '内容333',
        userId: 1
    },
    {
        content: '内容444',
        userId: 2
    },
    {
        content: '内容555',
        userId: 2
    }
])

关联查询

定义好模型和模型之间的关系之后,我们就可以开始进行关联查询了。

User.findAll({ include: Comment })
        .then((result) => {
            res.send(result)
        })
        .catch((error) => {
            console.log(error)
        })

最后呈现的数据如下:

[
    {
        "id": 1,
        "username": "shiramashiro",
        "password": "654321",
        "createdAt": "2021-11-05T10:43:29.000Z",
        "updatedAt": "2021-11-05T10:43:29.000Z",
        "comments": [
            {
                "id": 3,
                "content": "内容333",
                "createdAt": "2021-11-05T10:43:29.000Z",
                "updatedAt": "2021-11-05T10:43:29.000Z",
                "userId": 1
            },
            {
                "id": 2,
                "content": "内容222",
                "createdAt": "2021-11-05T10:43:29.000Z",
                "updatedAt": "2021-11-05T10:43:29.000Z",
                "userId": 1
            },
            {
                "id": 1,
                "content": "内容111",
                "createdAt": "2021-11-05T10:43:29.000Z",
                "updatedAt": "2021-11-05T10:43:29.000Z",
                "userId": 1
            }
        ]
    },
    {
        "id": 2,
        "username": "javascript",
        "password": "js123456",
        "createdAt": "2021-11-05T10:43:29.000Z",
        "updatedAt": "2021-11-05T10:43:29.000Z",
        "comments": [
            {
                "id": 5,
                "content": "内容555",
                "createdAt": "2021-11-05T10:43:29.000Z",
                "updatedAt": "2021-11-05T10:43:29.000Z",
                "userId": 2
            },
            {
                "id": 4,
                "content": "内容444",
                "createdAt": "2021-11-05T10:43:29.000Z",
                "updatedAt": "2021-11-05T10:43:29.000Z",
                "userId": 2
            }
        ]
    }
]

结合 Express 开发接口

对于上面的查询方法,我们可以设计一个 HTTP API 接口,供前端项目使用。

const express = require('express')
const app = express()

app.get('/', (req, res) => {
  User.findAll({ include: Comment })
        .then((result) => {
            res.send(result)
        })
        .catch((error) => {
            console.log(error)
        })
})

app.listen(3000, () => { console.log('server was running at 3000...') })

总结

在编程中,把面向对象的概念跟数据库中表的概念对应起来。ORM 的好处就是不用操作表,可以在程序中用面向对象的思路,直接操作对象即可。Sequelize 基于这样的程序设计技术,为我们提供了大量的可操作数据库的方法。比如 bulkCreate 批量插入数据,我们只需要直接调用方法即可,Sequelize 会自动为我们生成 SQL 语句。

文章同博客园:https://www.cnblogs.com/shiramashiro/p/15514580.html