使用Sequelize8

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了使用Sequelize8相关的知识,希望对你有一定的参考价值。

访问mysql

当我们安装好MySQL后,Node.js程序如何访问MySQL数据库呢?

访问MySQL数据库只有一种方法,就是通过网络发送SQL命令,然后,MySQL服务器执行后返回结果。

我们可以在命令行窗口输入​​mysql -u root -p​​,然后输入root口令后,就连接到了MySQL服务器。因为没有指定​​--host​​参数,所以我们连接到的是​​localhost​​,也就是本机的MySQL服务器。

在命令行窗口下,我们可以输入命令,操作MySQL服务器:

mysql> show databases;
+--------------------+
| Database |
+--------------------+
| information_schema |
| mysql |
| performance_schema |
| test |
+--------------------+
4 rows in set (0.05 sec)

输入​​exit​​退出MySQL命令行模式。

对于Node.js程序,访问MySQL也是通过网络发送SQL命令给MySQL服务器。这个访问MySQL服务器的软件包通常称为MySQL驱动程序。不同的编程语言需要实现自己的驱动,MySQL官方提供了Java、.Net、Python、Node.js、C++和C的驱动程序,官方的Node.js驱动目前仅支持5.7以上版本,而我们上面使用的命令行程序实际上用的就是C驱动。

目前使用最广泛的MySQL Node.js驱动程序是开源的​​mysql​​,可以直接使用npm安装。

ORM

如果直接使用​​mysql​​包提供的接口,我们编写的代码就比较底层,例如,查询代码:

connection.query(SELECT * FROM users WHERE id = ?, [123], function(err, rows) 
if (err)
// error
else
for (let row in rows)
processRow(row);


);

考虑到数据库表是一个二维表,包含多行多列,例如一个​​pets​​的表:

mysql> select * from pets;
+----+--------+------------+
| id | name | birth |
+----+--------+------------+
| 1 | Gaffey | 2007-07-07 |
| 2 | Odie | 2008-08-08 |
+----+--------+------------+
2 rows in set (0.00 sec)

每一行可以用一个javascript对象表示,例如第一行:


"id": 1,
"name": "Gaffey",
"birth": "2007-07-07"

这就是传说中的ORM技术:Object-Relational Mapping,把关系数据库的表结构映射到对象上。是不是很简单?

但是由谁来做这个转换呢?所以ORM框架应运而生。

我们选择Node的ORM框架Sequelize来操作数据库。这样,我们读写的都是JavaScript对象,Sequelize帮我们把对象变成数据库中的行。

用Sequelize查询​​pets​​表,代码像这样:

Pet.findAll()
.then(function (pets)
for (let pet in pets)
console.log(`$pet.id: $pet.name`);

).catch(function (err)
// error
);

因为Sequelize返回的对象是Promise,所以我们可以用​​then()​​和​​catch()​​分别异步响应成功和失败。

但是用​​then()​​和​​catch()​​仍然比较麻烦。有没有更简单的方法呢?

可以用ES7的await来调用任何一个Promise对象,这样我们写出来的代码就变成了:

var pets = await Pet.findAll();

真的就是这么简单!

await只有一个限制,就是必须在async函数中调用。上面的代码直接运行还差一点,我们可以改成:

(async () => 
var pets = await Pet.findAll();
)();

考虑到koa的处理函数都是async函数,所以我们实际上将来在koa的async函数中直接写await访问数据库就可以了!

这也是为什么我们选择Sequelize的原因:只要API返回Promise,就可以用await调用,写代码就非常简单!

实战

在使用Sequlize操作数据库之前,我们先在MySQL中创建一个表来测试。我们可以在​​test​​数据库中创建一个​​pets​​表。​​test​​数据库是MySQL安装后自动创建的用于测试的数据库。在MySQL命令行执行下列命令:

grant all privileges on test.* to www@% identified by www;

use test;

create table pets (
id varchar(50) not null,
name varchar(100) not null,
gender bool not null,
birth varchar(10) not null,
createdAt bigint not null,
updatedAt bigint not null,
version bigint not null,
primary key (id)
) engine=innodb;

第一条​​grant​​命令是创建MySQL的用户名和口令,均为​​www​​,并赋予操作​​test​​数据库的所有权限。

第二条​​use​​命令把当前数据库切换为​​test​​。

第三条命令创建了​​pets​​表。

然后,我们根据前面的工程结构创建​​hello-sequelize​​工程,结构如下:

hello-sequelize/
|
+- .vscode/
| |
| +- launch.json <-- VSCode 配置文件
|
+- init.txt <-- 初始化SQL命令
|
+- config.js <-- MySQL配置文件
|
+- app.js <-- 使用koa的js
|
+- package.json <-- 项目描述文件
|
+- node_modules/ <-- npm安装的所有依赖包

然后,添加如下依赖包:

"sequelize": "3.24.1",
"mysql": "2.11.1"

注意​​mysql​​是驱动,我们不直接使用,但是​​sequelize​​会用。

用​​npm install​​安装。

​config.js​​实际上是一个简单的配置文件:

var config = 
database: test, // 使用哪个数据库
username: www, // 用户名
password: www, // 口令
host: localhost, // 主机名
port: 3306 // 端口号,MySQL默认3306
;

module.exports = config;

下面,我们就可以在​​app.js​​中操作数据库了。使用Sequelize操作MySQL需要先做两件准备工作:

第一步,创建一个sequelize对象实例:

const Sequelize = require(sequelize);
const config = require(./config);

var sequelize = new Sequelize(config.database, config.username, config.password,
host: config.host,
dialect: mysql,
pool:
max: 5,
min: 0,
idle: 30000

);

第二步,定义模型Pet,告诉Sequelize如何映射数据库表:

var Pet = sequelize.define(pet, 
id:
type: Sequelize.STRING(50),
primaryKey: true
,
name: Sequelize.STRING(100),
gender: Sequelize.BOOLEAN,
birth: Sequelize.STRING(10),
createdAt: Sequelize.BIGINT,
updatedAt: Sequelize.BIGINT,
version: Sequelize.BIGINT
,
timestamps: false
);

用​​sequelize.define()​​定义Model时,传入名称​​pet​​,默认的表名就是​​pets​​。第二个参数指定列名和数据类型,如果是主键,需要更详细地指定。第三个参数是额外的配置,我们传入​​ timestamps: false ​​是为了关闭Sequelize的自动添加timestamp的功能。所有的ORM框架都有一种很不好的风气,总是自作聪明地加上所谓“自动化”的功能,但是会让人感到完全摸不着头脑。

接下来,我们就可以往数据库中塞一些数据了。我们可以用Promise的方式写:

var now = Date.now();

Pet.create(
id: g- + now,
name: Gaffey,
gender: false,
birth: 2007-07-07,
createdAt: now,
updatedAt: now,
version: 0
).then(function (p)
console.log(created. + JSON.stringify(p));
).catch(function (err)
console.log(failed: + err);
);

也可以用await写:

(async () => 
var dog = await Pet.create(
id: d- + now,
name: Odie,
gender: false,
birth: 2008-08-08,
createdAt: now,
updatedAt: now,
version: 0
);
console.log(created: + JSON.stringify(dog));
)();

显然await代码更胜一筹。

查询数据时,用await写法如下:

(async () => 
var pets = await Pet.findAll(
where:
name: Gaffey

);
console.log(`find $pets.length pets:`);
for (let p of pets)
console.log(JSON.stringify(p));

)();

如果要更新数据,可以对查询到的实例调用​​save()​​方法:

(async () => 
var p = await queryFromSomewhere();
p.gender = true;
p.updatedAt = Date.now();
p.version ++;
await p.save();
)();

如果要删除数据,可以对查询到的实例调用​​destroy()​​方法:

(async () => 
var p = await queryFromSomewhere();
await p.destroy();
)();

运行代码,可以看到Sequelize打印出的每一个SQL语句,便于我们查看:

Executing (default): INSERT INTO `pets` (`id`,`name`,`gender`,`birth`,`createdAt`,`updatedAt`,`version`) VALUES (g-1471961204219,Gaffey,false,2007-07-07,1471961204219,1471961204219,0);

Model

我们把通过​​sequelize.define()​​返回的​​Pet​​称为Model,它表示一个数据模型。

我们把通过​​Pet.findAll()​​返回的一个或一组对象称为Model实例,每个实例都可以直接通过​​JSON.stringify​​序列化为JSON字符串。但是它们和普通JSON对象相比,多了一些由Sequelize添加的方法,比如​​save()​​和​​destroy()​​。调用这些方法我们可以执行更新或者删除操作。

所以,使用Sequelize操作数据库的一般步骤就是:

首先,通过某个Model对象的​​findAll()​​方法获取实例;

如果要更新实例,先对实例属性赋新值,再调用​​save()​​方法;

如果要删除实例,直接调用​​destroy()​​方法。

注意​​findAll()​​方法可以接收​​where​​、​​order​​这些参数,这和将要生成的SQL语句是对应的。

以上是关于使用Sequelize8的主要内容,如果未能解决你的问题,请参考以下文章

当今的社会风气污浊不堪,国家--在视而不见,媒体--在故意误导

JZOJ5913 林下风气

requestbs4爬虫

生命力 学习力 生产力

2022给30+程序员2023年的忠告

2022给30+程序员2023年的忠告