教你egg.js如何连接Sequelize

教你egg.js如何连接Sequelize

1、 首先确保你机器上已经安装好MySQL了

1
sudo apt-get install mysql-server mysql-client

2、 然后用npm初始化一个项目

1
2
3
mkdir sequelize-project && cd sequelize-project
npm init egg --type=simple
npm i

安装并配置 egg-sequelize 插件(它会辅助我们将定义好的 Model 对象加载到 app 和 ctx 上)和 mysql2 模块:

1
npm install --save egg-sequelize mysql2

config/plugin.js中引入 egg-sequelize 插件

1
2
3
4
exports.sequelize = {
enable: true,
package: 'egg-sequelize',
};

config/config.default.js中编写 sequelize 配置

1
2
3
4
5
6
7
8
config.sequelize = {
dialect: 'mysql',
host: '127.0.0.1',
port: 3306,
database: 'egg-sequelize-doc-default',
username: "root",
password: "root",
};

3、初始化数据库和 Migrations
接下来我们先暂时离开 egg 项目的代码,设计和初始化一下我们的数据库。首先我们通过 mysql 命令在本地快速创建开发用到的 database:

1
mysql -u root -e 'CREATE DATABASE IF NOT EXISTS `egg-sequelize-doc-default`;'

4、安装 sequelize-cli

1
npm install --save-dev sequelize-cli

在 egg 项目中,我们希望将所有数据库 Migrations 相关的内容都放在database目录下,所以我们在项目根目录下新建一个.sequelizerc配置文件:

1
2
3
4
5
6
7
8
9
10
'use strict';

const path = require('path');

module.exports = {
config: path.join(__dirname, 'database/config.json'),
'migrations-path': path.join(__dirname, 'database/migrations'),
'seeders-path': path.join(__dirname, 'database/seeders'),
'models-path': path.join(__dirname, 'app/model'),
};

初始化 Migrations 配置文件和目录

1
2
npx sequelize init:config
npx sequelize init:migrations

执行完后会生成database/config.json文件和database/migrations目录,我们修改一下database/config.json中的内容,将其改成我们项目中使用的数据库配置:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
{
"development": {
"username": "root",
"password": null,
"database": "egg-sequelize-doc-default",
"host": "127.0.0.1",
"dialect": "mysql"
},
"test": {
"username": "root",
"password": null,
"database": "egg-sequelize-doc-unittest",
"host": "127.0.0.1",
"dialect": "mysql"
}
}

此时 sequelize-cli 和相关的配置也都初始化好了,我们可以开始编写项目的第一个 Migration 文件来创建我们的一个 users 表了。

1
npx sequelize migration:generate --name=init-users

执行完后会在database/migrations目录下生成一个 migration 文件(${timestamp}-init-users.js),我们修改它来处理初始化users表:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
'use strict';

module.exports = {
// 在执行数据库升级时调用的函数,创建 users 表
up: async (queryInterface, Sequelize) => {
const { INTEGER, DATE, STRING } = Sequelize;
await queryInterface.createTable('users', {
id: { type: INTEGER, primaryKey: true, autoIncrement: true },
name: STRING(30),
age: INTEGER,
created_at: DATE,
updated_at: DATE,
});
},
// 在执行数据库降级时调用的函数,删除 users 表
down: async queryInterface => {
await queryInterface.dropTable('users');
},
};

执行 migrate 进行数据库变更

1
2
3
4
5
6
# 升级数据库
npx sequelize db:migrate
# 如果有问题需要回滚,可以通过 `db:migrate:undo` 回退一个变更
# npx sequelize db:migrate:undo
# 可以通过 `db:migrate:undo:all` 回退到初始状态
# npx sequelize db:migrate:undo:all

执行之后,我们的数据库初始化就完成了。

5、编写代码
现在终于可以开始编写代码实现业务逻辑了,首先我们来在app/model/目录下编写 user 这个 Model:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// app/model/user.js
'use strict';

module.exports = app => {
const { STRING, INTEGER, DATE } = app.Sequelize;

const User = app.model.define('user', {
id: { type: INTEGER, primaryKey: true, autoIncrement: true },
name: STRING(30),
age: INTEGER,
created_at: DATE,
updated_at: DATE,
});

return User;
};

这个 Model 就可以在 Controller 和 Service 中通过app.model.User或者ctx.model.User访问到了,例如我们编写app/controller/users.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
// app/controller/users.js
const Controller = require('egg').Controller;

function toInt(str) {
if (typeof str === 'number') return str;
if (!str) return str;
return parseInt(str, 10) || 0;
}

class UserController extends Controller {
async index() {
const ctx = this.ctx;
const query = { limit: toInt(ctx.query.limit), offset: toInt(ctx.query.offset) };
ctx.body = await ctx.model.User.findAll(query);
}

async show() {
const ctx = this.ctx;
ctx.body = await ctx.model.User.findByPk(toInt(ctx.params.id));
}

async create() {
const ctx = this.ctx;
const { name, age } = ctx.request.body;
const user = await ctx.model.User.create({ name, age });
ctx.status = 201;
ctx.body = user;
}

async update() {
const ctx = this.ctx;
const id = toInt(ctx.params.id);
const user = await ctx.model.User.findByPk(id);
if (!user) {
ctx.status = 404;
return;
}

const { name, age } = ctx.request.body;
await user.update({ name, age });
ctx.body = user;
}

async destroy() {
const ctx = this.ctx;
const id = toInt(ctx.params.id);
const user = await ctx.model.User.findByPk(id);
if (!user) {
ctx.status = 404;
return;
}

await user.destroy();
ctx.status = 200;
}
}

module.exports = UserController;

最后我们将这个 controller 挂载到路由上:

1
2
3
4
5
// app/router.js
module.exports = app => {
const { router, controller } = app;
router.resources('users', '/users', controller.users);
};

针对users表的 CURD 操作的接口就开发完了。

如果出现了 csrf 安全验证的话,可以在config/config.default.js加上如下代码关闭 csrf:

1
2
3
4
5
6
7
8
9
10
11
.
.
.
config.security = {
csrf: {
enable: false,
},
};
.
.
.

刘伟 wechat
欢迎您扫一扫上面的微信公众号( 或者搜索:darrenliuwei )订阅
如果觉得本文对您有启发,可以随意打赏一点鼓励我继续更新!