egg.js:egg-sequelize插件管理数据库

使用egg-sequelize连接数据库组织数据请求、数据库管理。

一、插件安装

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

  • 安装
npm install egg-sequelize mysql2  --save
  • 引入插件

在 config/plugin.js 中引入 egg-sequelize 插件,根据写法有以下两种形式:

exports.sequelize = {
enable: true,
package: 'egg-sequelize',
};
module.exports = {
    sequelize: {
      enable: true,
      package: 'egg-sequelize',
  },
};
  • 基础配置

在 config/config.default.js 中编写 sequelize 配置(注意:启用egg-sequelize插件后,egg启动后会链接数据库,使用的是该配置,所以要指定对账号、密码、数据库等信息。与下文《Migrations管理数据库》中的配置文件不一样,那里的配置文件只用于命令行)

config.sequelize = {
dialect: 'mysql',
database: 'database_development',
host: '127.0.0.1',
port: '3306',
username: 'root',
password: '你的密码',
timezone: '+08:00',
};

二、使用sequelize-cli实现Migrations管理数据库

虽然可以直接通过 mysql 命令将表直接建好,但是这并不是一个对多人协作非常友好的开发模式。在项目的演进过程中,每一个迭代都有可能对数据库数据结构做变更,怎样跟踪每一个迭代的数据变更,并在不同的环境(开发、测试、CI)和迭代切换中,快速变更数据结构?这时就需要 Migrations 来管理数据结构的变更。

sequelize 提供了 sequelize-cli 工具来实现 Migrations,可以在 egg 项目中引入 sequelize-cli。

  • 安装 sequelize-cli
npm install --save-dev sequelize-cli

在 egg 项目中,我们希望将所有数据库 Migrations 相关的内容都放在 database 目录下,所以在项目根目录下新建一个 .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'),
};
  • 初始化 Migrations 配置文件和目录
npx sequelize init:config
npx sequelize init:migrations

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

{
"development": {
"username": "root",
"password": "mypassword",
"database": "database_development",
"host": "127.0.0.1",
"dialect": "mysql"
},
"test": {
"username": "root",
"password": "mypassword",
"database": "database_test",
"host": "127.0.0.1",
"dialect": "mysql"
},
 "production": {
    "username": "root",
    "password": "mypassword",
    "database": "database_production",
    "host": "127.0.0.1",
    "dialect": "mysql"
  }
}

注意把彩色文字部分换成你想要的数据库名字,并输入你安装数据库时设置的密码。

运行以下命令会根据配置文件创建数据库(执行npx sequelize命令可以查看可以执行的各种命令),会根据环境创建相应数据库,默认是development环境。

npx sequelize db:create --charset "utf8mb4"
//注意:一定要加上字符集,否则无法在数据库中使用中文字符。

注意添加字符集参数,否则无法保存中文。

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

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

执行完后会在 database/migrations 目录下生成一个 migration 文件(${timestamp}-init-users.js),我们修改它来处理初始化 users 表(注意STRING若不指定数字,默认=VARCHAR(255)),数据类型可以参考https://github.com/demopark/sequelize-docs-Zh-CN/blob/master/core-concepts/model-basics.md

'use strict';
module.exports = {
// 在执行数据库升级时调用的函数,创建 users 表

  up: async (queryInterface, Sequelize) => {
    const {INTEGER,DATE,STRING} = Sequelize;
    await queryInterface.createTable('users',{
      userid:{type:STRING(12),primaryKey:true},
      username:{type:STRING(30),allowNull:false,},
      deptNo:{type:INTEGER,allowNull:false,},
      classNo:{type:INTEGER,allowNull:false,},      
      isExpert:{type:INTEGER,defaultValue:0,allowNULL:false,},
      fielddNo:{type:INTEGER,defaultValue:0,allowNULL:false,},
      created_at:DATE,
      updated_at:DATE,
    });
  },
// 在执行数据库降级时调用的函数,删除 users 表

down: async queryInterface => {
await queryInterface.dropTable('users');
},
};
  • 执行 migrate 进行数据库变更
# 升级数据库
npx sequelize db:migrate
# 如果有问题需要回滚,可以通过 `db:migrate:undo` 回退一个变更
# npx sequelize db:migrate:undo
# 可以通过 `db:migrate:undo:all` 回退到初始状态
# npx sequelize db:migrate:undo:all
# 可以通过 `db:migrate:undo:    --name  migration 文件名(不含.js)` 回退指定名称的migration

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

  • 问题备注

定义表格时,可以使用references设置外键(如: references: {  model: ‘classes’,  key: ‘classno’, },),但是似乎容易出问题,后来旧没设置外键了。

三、egg-sequelize使用

1、model定义

model是现业务逻辑的基础,其可以认为是对应一个数据库的表格,定义的内容与上面migration中内容类似,在app/model目录下编写对应model(如下文的User),这个 Model 就可以在 Controller 和 Service 中通过 app.model.User 或者 ctx.model.User 访问到(数据类型可以参考https://github.com/demopark/sequelize-docs-Zh-CN/blob/master/core-concepts/model-basics.md):

'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,
  }, {
    // tableName: '实际数据表名',
    freezeTableName: true,  //锁定表名,禁止自动转换(默认会变复数)
    timestamps: true,     //自动维护createdAt、updatedAt
    undercored: true,    //自动将驼峰属性名转换为数据库中的下划线格式(比如createdAt -> created_at)
  });
  return User;
};

注意:增加model后启动时可能会报:app.model.define is not a function的错误,原因是之前执行以下代码时在app/model目录下生成了一个index.js文件,这个文件会导致报错。

npx sequelize init

解决方法是删除该index.js文件,或者修改config/config.default.js文件在sequelize配置中增加: excluede:’index.js’。

app.model.define第一个参数名称可与model名不一致,实际model是与model的文件名相关(首字母会被大写),第一个参数名默认应为数据库的表名。若不是表名,可以增加第3个参数,在参数的tableName属性指定实际数据库的指明。

2、model使用

上文编写的model可以在 Controller 和 Service 中通过 app.model.User 或者 ctx.model.User 访问到。

然后可以使用sequelize在model上的方法,如:findAll、findByPk、create之类,具体可以执行哪些,可以参照sequelize的文档

发表评论

邮箱地址不会被公开。 必填项已用*标注

回到顶部