Eggjs学习系列(五) Sequelize的使用
简单的数据库操作通过使用egg-mysql 插件基本上可以满足需求,而在一些较为复杂的应用中,我们可能会需要一个 ORM 框架来帮助我们管理数据层的代码。sequelize 是一个广泛使用的 ORM 框架,支持多种数据库。ORM 即使用面向对象的方式,通过操作对象来实现与数据库之前的交流,完成CRUD的动作。
安装和配置插件
由于我们使用的是 TypeScript 语言,这里采用的是 egg-sequelize-ts 插件,插件使用 sequelize-typescript 来操作数据库。
npm install --save egg-sequelize-ts mysql2
在 config/plugin.ts 中引入 egg-sequelize 插件
const plugin: EggPlugin = {
// static: true,
sequelize: {
enable: true,
package: 'egg-sequelize-ts',
},
};
在 config/config.default.ts 中编写 sequelize 配置
import { EggAppConfig, EggAppInfo, PowerPartial } from 'egg';
export default (appInfo: EggAppInfo) => {
const config = {} as PowerPartial<EggAppConfig>;
// add your special config in here
const bizConfig = {
sequelize: {
dialect: 'mysql',
host: '127.0.0.1',
port: 3306,
password: 'xxx',
database: 'egg',
},
}
// the return config will combines to EggAppConfig
return {
...config,
...bizConfig,
};
};
Sequelize-cli 使用
在日常开发种,经常会遇到数据库结构发生变更的情况,这时候需要使用 Migrations 来管理数据结构的变更,以实现在不同的开发环境和迭代切换中,快速变更数据结构。
安装 sequelize-cli
npm install --save sequelize-cli
在Nodejs Web应用中建立初始的数据访问层
npx sequelize init
将创建以下文件夹:
config包含配置文件,它告诉CLI如何连接数据库models包含您的项目的所有模型migrations包含所有迁移文件seeders包含所有种子文件
注意: 可以通过 .sequelizerc 设置 生成文件夹的位置。
// .sequelizerc
'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'),
};
sequelize-cli 常用命令
npx sequelize db:create # 创建数据库
npx sequelize db:drop # 删除数据库
# 通过命令行创建模型,使用 model:generate 命令
# name: 模型名称
# attributes: 模型的属性列表
# 创建模型 User, 模型包括属性 firstName、lastName、email
npx sequelize model:generate --name User --attributes firstName:string,lastName:string,email:string
# 创建模型 Role, 模型包括属性 roleName
npx sequelize model:generate --name Role --attributes roleName:string
# 数据库迁移
npx sequelize db:migrate
# 撤销上一次迁移操作
# 可使用 --name xxx 指定具体迁移
npx sequelize db:migrate:undo
# 撤销所有迁移操作
npx sequelize db:migrate:undo:all
# 创建种子,用于生成测试数据
npx sequelize seed:generate --name demo-role
npx sequelize seed:generate --name demo-user
# 插入演示数据到数据库种
npx sequelize db:seed:all
# 撤销指定种子文件
npx sequelize db:seed:undo --seed 指定种子文件
# 撤销所有种子文件
db:seed:undo:all
sequelize-cli 实践
在eggjs项目中创建 database 目录存放数据库信息。根据上面的 .sequelizrc 文件,执行指令
npx sequelize init:config
npx sequelize init:migrations
会生成 database/config.json 文件和 database/migrations 目录,修改 database/config.json 中的服务器配置。修改好配置,生成一个 migration 文件。
npx sequelize migration:generate --name=init-users
通过生成的 migration文件来初始化表。sequelize-cli 默认生成的 js 文件,修改文件后缀为 ts 编写内容
// ${timestamp}-init-users.ts 文件
import { QueryInterface } from 'sequelize';
export default {
up: async (queryInterface: QueryInterface, Sequelize) => {
const { INTEGER, STRING, DATE } = Sequelize;
await queryInterface.createTable('users', {
id: { type: INTEGER, primaryKey: true, autoIncrement: true },
name: STRING(30),
age: INTEGER,
created_at: DATE,
updated_at: DATE,
});
},
down: async (queryInterface: QueryInterface) => {
await queryInterface.dropTable('users');
},
};
sequelize-cli 执行 migrate 进行数据库变更
# 升级数据库
npx sequelize db:migrate
# 如果有问题需要回滚,可以通过 `db:migrate:undo` 回退一个变更
# npx sequelize db:migrate:undo
# 可以通过 `db:migrate:undo:all` 回退到初始状态
# npx sequelize db:migrate:undo:all
正常的 js 文件在执行完上面的步骤后,便完成了迁移,但由于我们采用了 typescript 语法,需要先进行处理:
-
在
package.json中添加执行命令"scripts": { "sequelize-cli-ts": "node -r ts-node/register ./node_modules/sequelize-cli/lib/sequelize" } -
执行命令
yarn sequelize-cli-ts db:migrate # yarn 执行 npm run sequelize-cli-ts db:migrate # npm 执行
sequelize 实践
在 app/model/ 目录下编写 user 这个 Model
import { AutoIncrement, Column, DataType, Model, PrimaryKey, Table } from 'sequelize-typescript';
@Table({
modelName: 'user',
timestamps: false,
})
export class User extends Model<User> {
@PrimaryKey
@AutoIncrement
@Column({
type: DataType.INTEGER(11),
comment: '用户ID',
})
id: number;
@Column({
type: DataType.STRING(30),
comment: '用户姓名',
})
name: string;
@Column({
comment: '用户年龄',
})
age: number;
}
export default () => User;
这个 Model 就可以在 Controller 和 Service 中通过 app.model.User 或者 ctx.model.User 访问到了,例如我们编写 app/controller/users.ts:
import { Controller } from 'egg';
function toInt(str) {
if (typeof str === 'number') return str;
if (!str) return str;
return parseInt(str, 10) || 0;
}
export default class UsersController extends Controller {
// 查询用户
public 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;
}
}
最后添加路由
import { Application } from 'egg';
export default (app: Application) => {
const { controller, router } = app;
// ...
router.resources('users', '/users', controller.users);
};
注意:
sequelize 默认添加数据的时候会增加一些常用字段如creatAt等等。如果不需要这些属性,可以在 @table 注解里设置取消
@Table({
tableName: "project",
timestamps: false,
freezeTableName: true
})
本文是Eggjs学习系列的第五部分,主要介绍了如何在Eggjs项目中集成和使用Sequelize ORM框架。内容涵盖Sequelize的安装配置、Sequelize-cli的使用,包括数据库结构的迁移和种子文件,以及如何在项目中创建和使用Model。此外,还提到了如何处理typescript与sequelize的集成问题。
 Sequelize的使用&spm=1001.2101.3001.5002&articleId=105556703&d=1&t=3&u=20cf653248b74a25888e8e00009925f7)
658

被折叠的 条评论
为什么被折叠?



