Sequelize 是一个基于 promise 的 Node.js ORM, 目前支持 Postgres, MySQL, SQLite 和 Microsoft SQL Server. 它具有强大的事务支持, 关联关系, 读取和复制等功能。
基于sequelize创建数据访问层和数据库
安装sequelize
1 | npm install --save sequelize |
2 | npm install --save mysql2 |
安装sequelize-cli
首先应安装sequelize-cli工具,可以选择全局安装,也可以选择本地安装。
1 | npm install --save-dev sequelize-cli |
2 | npm install -g sequelize-cli |
建立初始的ORM引导框架
在Nodejs Web应用中建立初始的数据访问层
1 | npx sequelize init |
这将创建以下文件夹:
- config, 包含配置文件,它告诉CLI如何连接数据库
- models,包含您的项目的所有模型
- migrations, 包含所有迁移文件
- seeders, 包含所有种子文件
修改配置文件以连接到数据库管理系统,并创建数据库
在建立模型之前,应先修改config/config.json,以告诉 CLI 如何连接到数据库。config/config.json内容如下:
1 | { |
2 | "development": { |
3 | "username": "root", |
4 | "password": "root", |
5 | "database": "database_development", |
6 | "host": "127.0.0.1", |
7 | "dialect": "mysql", |
8 | "operatorsAliases": false |
9 | }, |
10 | "test": { |
11 | "username": "root", |
12 | "password": "root", |
13 | "database": "database_test", |
14 | "host": "127.0.0.1", |
15 | "dialect": "mysql", |
16 | "operatorsAliases": false |
17 | }, |
18 | "production": { |
19 | "username": "root", |
20 | "password": "root", |
21 | "database": "database_production", |
22 | "host": "127.0.0.1", |
23 | "dialect": "mysql", |
24 | "operatorsAliases": false |
25 | } |
26 | } |
使用如下命令创建数据库:
1 | npx sequelize db:create |
使用如下命令删除数据库:
1 | npx sequelize db:drop |
创建模型
我们将使用 model:generate 命令。 此命令需要两个选项:
- name, 模型的名称
- attributes, 模型的属性列表
创建一个名叫 User 的模型:
1 | npx sequelize model:generate --name User --attributes firstName:string,lastName:string,email:string |
这将创建一下文件:
- 在 models 文件夹中创建了一个 user 模型文件
- 在 migrations 文件夹中创建了一个名字像 XXXXXXXXXXXXXX-create-user.js 的迁移文件
注意: _Sequelize 将只使用模型文件,它是表描述。另一边,迁移文件是该模型的更改,或更具体的是说 CLI 所使用的表。 处理迁移,如提交或日志,以进行数据库的某些更改。
再创建一个名为Role的模型,它跟User是一对多的关系:
1 | npx sequelize model:generate --name Role --attributes roleName:string |
定义关系
Role和User是一对多的关系,因此需要修改它们的模型定义。
修改models/role.js如下:
1 | ; |
2 | module.exports = (sequelize, DataTypes) => { |
3 | var Role = sequelize.define('Role', { |
4 | roleName: DataTypes.STRING |
5 | }, {}); |
6 | Role.associate = function(models) { |
7 | // associations can be defined here |
8 | Role.hasMany(models.User) |
9 | }; |
10 | return Role; |
11 | }; |
修改models/user.js如下:
1 | ; |
2 | module.exports = (sequelize, DataTypes) => { |
3 | const User = sequelize.define('User', { |
4 | firstName: DataTypes.STRING, |
5 | lastName: DataTypes.STRING, |
6 | email: DataTypes.STRING |
7 | }, {}); |
8 | User.associate = function(models) { |
9 | // associations can be defined here |
10 | User.belongsTo(models.Role, { |
11 | onDelete: "NULL", |
12 | foreignKey: { |
13 | allowNull: false |
14 | } |
15 | }) |
16 | }; |
17 | return User; |
18 | }; |
修改和运行迁移
Role和User是一对多的关系,因此需要修改User迁移文件的定义。
修改migrates/XXXXXXXXXXXXXX-create-user.js如下:
1 | ; |
2 | module.exports = { |
3 | up: (queryInterface, Sequelize) => { |
4 | return queryInterface.createTable('Users', { |
5 | id: { |
6 | allowNull: false, |
7 | autoIncrement: true, |
8 | primaryKey: true, |
9 | type: Sequelize.INTEGER |
10 | }, |
11 | roleId: { // name of the key we're adding |
12 | type: Sequelize.INTEGER, |
13 | allowNull: false, |
14 | references: { |
15 | model: 'Roles', // name of Target model |
16 | key: 'id', // key in Target model that we're referencing |
17 | }, |
18 | onUpdate: 'CASCADE', |
19 | onDelete: 'CASCADE', |
20 | }, |
21 | firstName: { |
22 | type: Sequelize.STRING |
23 | }, |
24 | lastName: { |
25 | type: Sequelize.STRING |
26 | }, |
27 | email: { |
28 | type: Sequelize.STRING |
29 | }, |
30 | createdAt: { |
31 | allowNull: false, |
32 | type: Sequelize.DATE |
33 | }, |
34 | updatedAt: { |
35 | allowNull: false, |
36 | type: Sequelize.DATE |
37 | } |
38 | }); |
39 | }, |
40 | down: (queryInterface, Sequelize) => { |
41 | return queryInterface.dropTable('Users'); |
42 | } |
43 | }; |
注意:这里主要给User添加了外键字段,外键字段命名有规则:通常为小写的模型名加Id,即驼峰风格。例如这里加了roleId的外键字段。
在数据库中实际创建该表,需要运行 db:migrate 命令。
1 | npx sequelize db:migrate |
此命令将执行这些步骤:
- 将在数据库中创建一个名为 SequelizeMeta 的表。 此表用于记录在当前数据库上运行的迁移
- 开始寻找尚未运行的任何迁移文件。 这可以通过检查 SequelizeMeta 表。 在这个例子中,它将运行创建的 XXXXXXXXXXXXXX-create-role.js和XXXXXXXXXXXXXX-create-user.js 迁移。
- 创建一个名为 Roles 的表,其中包含其迁移文件中指定的所有列。
- 创建一个名为 Users 的表,其中包含其迁移文件中指定的所有列。
撤销迁移
撤销上一次的迁移操作
1 | npx sequelize db:migrate:undo |
撤销所有的迁移操作
1 | npx sequelize db:migrate:undo:all |
具体迁移脚本
1 | npx sequelize db:migrate:undo --name xxx |
创建种子,生成测试数据
创建几个用户和角色:
1 | npx sequelize seed:generate --name demo-role |
2 | npx sequelize seed:generate --name demo-user |
这个命令将会在 seeders 文件夹中创建两个种子文件。文件名看起来像是 XXXXXXXXXXXXXX-demo-role.js和XXXXXXXXXXXXXX-demo-user.js,它遵循相同的 up/down 语义,如迁移文件。
现在我们应该编辑这两个文件,将演示角色插入Role表,将演示用户插入User表。修改XXXXXXXXXXXXXX-demo-role.js如下:
1 | ; |
2 | |
3 | module.exports = { |
4 | up: (queryInterface, Sequelize) => { |
5 | return queryInterface.bulkInsert('Roles', [{ |
6 | roleName: '管理员', |
7 | createdAt:new Date(), |
8 | updatedAt:new Date() |
9 | },{ |
10 | roleName: '普通用户', |
11 | createdAt:new Date(), |
12 | updatedAt:new Date() |
13 | }], {}); |
14 | |
15 | }, |
16 | |
17 | down: (queryInterface, Sequelize) => { |
18 | return queryInterface.bulkDelete('Roles', null, {}); |
19 | |
20 | } |
21 | }; |
修改XXXXXXXXXXXXXX-demo-user.js如下:
1 | ; |
2 | |
3 | module.exports = { |
4 | up: (queryInterface, Sequelize) => { |
5 | return queryInterface.bulkInsert('Users', [{ |
6 | roleId:1, |
7 | firstName: 'John', |
8 | lastName: 'Doe', |
9 | email: 'demo@demo.com', |
10 | createdAt:new Date(), |
11 | updatedAt:new Date() |
12 | },{ |
13 | roleId:1, |
14 | firstName: 'Jack', |
15 | lastName: 'Smith', |
16 | email: 'jack@demo.com', |
17 | createdAt:new Date(), |
18 | updatedAt:new Date() |
19 | }], {}); |
20 | |
21 | }, |
22 | |
23 | down: (queryInterface, Sequelize) => { |
24 | return queryInterface.bulkDelete('Users', null, {}); |
25 | } |
26 | }; |
种子文件修改后,即可使用如下命令将演示数据插入数据库中:
1 | npx sequelize db:seed:all |
存储记录
1 | "seederStorage": "json", |
2 | "seederStoragePath": "sequelizeData.json", |
3 | "seederStorageTableName": "sequelize_data" |
撤销种子文件
撤销指定种子文件
1 | npx sequelize db:seed:undo --seed 指定种子文件 |
撤销所有种子文件
1 | db:seed:undo:all |