使用Sequelize
访问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语句是对应的。
文档
Sequelize的API可以参考官方文档。
参考源码
使用Sequelize的更多相关文章
- nodejs项目mysql使用sequelize支持存储emoji
nodejs项目mysql使用sequelize支持存储emoji 本篇主要记录nodejs项目阿里云mysql如何支持存储emoji表情. 因由 最近项目遇到用户在文本输入emoji进行存储的时候导 ...
- 在node.js中,使用基于ORM架构的Sequelize,操作mysql数据库之增删改查
Sequelize是一个基于promise的关系型数据库ORM框架,这个库完全采用JavaScript开发并且能够用在Node.JS环境中,易于使用,支持多SQL方言(dialect),.它当前支持M ...
- sequelize常见操作使用方法
关于sequelize的准备工作这里不再赘述. 一.引入sequelize模块 var Sequelize = require('sequelize'); 二.连接数据库 var sequelize ...
- nodejs+sequelize操作mysql数据库
前言: 本人对mysql不是很熟悉,只会命令行的简单增删改查.有些观点可能不到位请谅解. sequelize是针对node.js和io.js开发的基于ORM的框架,它支持的数据库包括:PostgreS ...
- Sequelize 关系模型简介
Sequelize 关系模型简介 先介绍一下本文用到的术语: 源: 调用 sequelize 中关系方法的调用者 目标: 调用 sequelize 中关系方法中的参数 比如, User.hasOne( ...
- Node.js ORM 框架 sequelize 实践
最近在做团队的一个内部系统,这次使用的nodejs web框架是团队统一的hapi.js,而数据库依然是mysql,ORM 框架选用有着6000+ stars 的 sequelize.js,hapi- ...
- sequelize翻译(1)
第一次翻译(由mongoose转了mysql) v 3.0.0 1.Sequelize类 2.sequelize对象 3.sequelize.define()返回的表对象 4.表对象的方法 1.Seq ...
- Sequelize 基本操作
Sequelize 是 Node 的一个 ORM(Object-Relational Mapping) 框架,用来方便数据库操作. 配置 sequelize 以 mysql 为例 首先我们要引入npm ...
- 【前端】nodejs的ORM框架sequelize的工厂化
转载请注明出处:http://www.cnblogs.com/shamoyuu/p/sequelize_factory.html 一.什么是sequelize nodejs的后台在操作数据库的时候,需 ...
- node.js应用脚手架:koa2、sequelize、mysql
自制了一个 nodejs 应用的脚手架. 基于 koa2 的,所以需要保证 node 环境至少为 7.6.0 吸取了以前的踩坑教训,添加了守护进程,确保应用不会因为异常导致网站直接挂掉(使用了 for ...
随机推荐
- 开发环境需要同时安装2个nodejs版本
由于同时有vue2和vue3的项目开发情况,vue2项目的nodejs版本是12,vue3项目在node12版本下运行不了,要求最低14版本,因此要用nvm同时安装和控制2个版本. 安装步骤: 1.卸 ...
- addEventListener添加事件监听
removeEventListener移除事件监听 window.addEventListener('mousedown', e => this.closeMenu(e)) window.add ...
- avue-crud字段之间的动态交互效果以及接口数据的获取赋值
一.form表单下拉表单类型字段数据获取 1.通过配置系统字典接口获取数据并渲染 { label: "经纪人", prop: "broker", type: & ...
- 牛逼!50.3K Star!一个自动将屏幕截图转换为代码的开源工具
1.背景 在当今快节奏的软件开发环境中,设计师与开发者之间的协同工作显得尤为重要.然而,理解并准确实现设计稿的意图常常需要耗费大量的时间和沟通成本.为此,开源社区中出现了一个引人注目的项目--scre ...
- FreeSWITCH使用soundtouch进行变声
操作系统 :CentOS 7.6_x64 FreeSWITCH版本 :1.10.9 FreeSWITCH里面有个mod_soundtouch模块,支持通话实时变声,今天整理下CentOS 7环境下 ...
- Windows10 LTSC版,比Win7还干净
在Windows操作系统的发展历程中,每一个版本都承载着微软对用户需求的深度理解和技术创新.其中,Windows 7以其稳定.高效和简洁的特点,赢得了众多用户的喜爱. 然而,随着技术的不断进步和用户需 ...
- 阿里bxet逆向
声明 本文章中所有内容仅供学习交流,抓包内容.敏感网址.数据接口均已做脱敏处理,严禁用于商业用途和非法用途,否则由此产生的一切后果均与作者无关,若有侵权,请联系我立即删除! 目标网站 x82y 分析过 ...
- 使用elementUI组件来完成前台展示
使用elementUI组件来完成前台展示,当然不是全部都用,有用到的时候,才用. 网址:https://element.eleme.cn/#/zh-CN 安装 cnpm i element-ui -S ...
- [SWPUCTF 2021 新生赛]easy_sql
这道题呢就是很简单的sql注入,我们直接用sqlmap来跑. 首先我们打开页面可以看见提示,参数为wllm **然后我们启动虚拟机,输入sqlmap的命令:sqlmap -u "url地址/ ...
- WPF/C#:程序关闭的三种模式
ShutdownMode枚举类型介绍 ShutdownMode是一个枚举类型,它定义了WPF应用程序的关闭方式.这个枚举类型有三个成员: OnLastWindowClose:当最后一个窗口关闭或者调用 ...