egg项目创建之连接配置(三)

本文涉及的产品
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 RDS PostgreSQL,高可用系列 2核4GB
云数据库 RDS MySQL,高可用系列 2核4GB
简介: 默认情况下,egg-sequelize 将使用 sequelize@5,您可以自定义 sequelize 版本使用 config.sequelize.Sequelize 绕过

egg的连接配置


  • 安装


$ npm i --save egg-sequelize
$ npm install --save mysql2 # For both mysql and mariadb dialects
或者使用其他方式连接
$ npm install --save pg pg-hstore
$ npm install --save tedious 


  • config/plugin.js里配置插件


exports.sequelize = {
    enable: true,
    package: 'egg-sequelize'
}


  • conif/config.{env}.js里进行连接配置


exports.sequelize = {
  delegate: 'model', // 加载所有的模型到 app.model and ctx.model
  baseDir: 'model', // 要加载的模型目录`app/model/*.js`
  dialect: 'mysql', // 支持的数据连接类型: mysql, mariadb, postgres, mssql
  database: 'test',
  host: 'localhost',
  port: 3306,
  username: 'root',
  password: '',
  // delegate: 'myModel', // load all models to `app[delegate]` and `ctx[delegate]`, default to `model`
  // baseDir: 'my_model', // load all files in `app/${baseDir}` as models, default to `model`
  // exclude: 'index.js', // ignore `app/${baseDir}/index.js` when load models, support glob and array
  // more sequelize options
  timezone: 'Asia/Shanghai', // 时间差
  benchmark: true,
  modelName: 'bar', // 这将控制自动生成的foreignKey和关联命名的名称
  timestamps: false, // 不添加时间戳属性 (updatedAt, createdAt)
  // 我不想要 createdAt
  createdAt: false,
  // 我想 updateAt 实际上被称为 updateTimestamp
  updatedAt: 'updateTimestamp',
  // 并且希望 deletedA t被称为 destroyTime(请记住启用paranoid以使其工作)
  deletedAt: 'destroyTime',
  // paranoid 只有在启用时间戳时才能工作
  paranoid: true,// 不删除数据库条目,但将新添加的属性deletedAt设置为当前日期(删除完成时). 
  underscored: true, // 将自动设置所有属性的字段参数为下划线命名方式.不会覆盖已经定义的字段选项
  freezeTableName: true,// 禁用修改表名; 默认情况下,sequelize将自动将所有传递的模型名称(define的第一个参数)转换为复数. 如果你不想这样,请设置以下内容
  tableName: 'my_very_custom_table_name',// 定义表的名称
  // 启用乐观锁定. 启用时,sequelize将向模型添加版本计数属性,
  // 并在保存过时的实例时引发OptimisticLockingError错误.
  // 设置为true或具有要用于启用的属性名称的字符串.
  version: true,
  define: {
      reezeTableName: true, // 禁止数据读写时给表赋别名(as)
      underscored: true,
      timestamps: false, // 为模型添加createdAt和updatedAt字段
  },
};


  • 也可以进行以下这样连接


exports.sequelize = {
      dialect: 'mysql', // support: mysql, mariadb, postgres, mssql
      connectionUri: 'mysql://root:@127.0.0.1:3306/test',
      // delegate: 'myModel', // load all models to `app[delegate]` and `ctx[delegate]`, default to `model`
      // baseDir: 'my_model', // load all files in `app/${baseDir}` as models, default to `model`
      // exclude: 'index.js', // ignore `app/${baseDir}/index.js` when load models, support glob and array
      // more sequelize options
};


  • egg-sequelize 有一个默认的 sequelize 选项如下


{
        delegate: 'model',
        baseDir: 'model',
        logging(...args) {
          // if benchmark enabled, log used
          const used = typeof args[1] === 'number' ? `[${args[1]}ms]` : '';
          app.logger.info('[egg-sequelize]%s %s', used, args[0]);
        },
        host: 'localhost',
        port: 3306,
        username: 'root',
        benchmark: true,
        define: {
          freezeTableName: false,
          underscored: true,
        },
};


模型文件


默认情况下,请将模型置于 app/model 目录下。


约定


model file class name
user.js app.model.User
person.js app.model.Person
user_group.js app.model.UserGroup
user/profile.js app.model.User.Profile


  • 表格始终具有时间戳字段:created_at datetimeupdated_at datetime


  • 使用下划线样式列名,如: user_idcomments_count


实例


标准


首先定义模型


注意:options.delegate 默认为 model,所以 app.modelSequelize实例, 可以使用如下方法:


app.model.sync, app.model.query ...


// app/model/user.js
module.exports = app => {
  const { STRING, INTEGER, DATE } = app.Sequelize;
  const User = app.model.define('user', {
    login: STRING,
    name: STRING(30),
    password: STRING(32),
    age: INTEGER,
    last_sign_in_at: DATE,
    created_at: DATE,
    updated_at: DATE,
  });
  User.findByLogin = async function(login) {
    return await this.findOne({
      where: {
        login: login
      }
    });
  }
  // don't use arraw function
  User.prototype.logSignin = async function() {
    return await this.update({ last_sign_in_at: new Date() });
  }
  return User;
};


现在您可以在控制器中使用它:


// app/controller/user.js
class UserController extends Controller {
  async index() {
    const users = await this.ctx.model.User.findAll();
    this.ctx.body = users;
  }
  async show() {
    const user = await this.ctx.model.User.findByLogin(this.ctx.params.login);
    await user.logSignin();
    this.ctx.body = user;
  }
}


关联


Model.associate() 中定义所有关联,egg-sequelize 将在加载所有模型后执行它。请参见下面的示例:


多数据源


egg-sequelize 支持独立加载多个数据源,您可以使用 config.sequelize.datasources 配置和加载多个数据源。


// config/config.default.js
exports.sequelize = {
  datasources: [
    {
      delegate: 'model', // load all models to app.model and ctx.model
      baseDir: 'model', // load models from `app/model/*.js`
      database: 'biz',
      // other sequelize configurations
    },
    {
      delegate: 'admninModel', // load all models to app.adminModel and ctx.adminModel
      baseDir: 'admin_model', // load models from `app/admin_model/*.js`
      database: 'admin',
      // other sequelize configurations
    },
  ],
};


我们可以这样定义模型:


// app/model/user.js
module.exports = app => {
  const { STRING, INTEGER, DATE } = app.Sequelize;
  const User = app.model.define('user', {
    login: STRING,
    name: STRING(30),
    password: STRING(32),
    age: INTEGER,
    last_sign_in_at: DATE,
    created_at: DATE,
    updated_at: DATE,
  });
  return User;
};


// app/admin_model/user.js
module.exports = app => {
  const { STRING, INTEGER, DATE } = app.Sequelize;
  const User = app.adminModel.define('user', {
    login: STRING,
    name: STRING(30),
    password: STRING(32),
    age: INTEGER,
    last_sign_in_at: DATE,
    created_at: DATE,
    updated_at: DATE,
  });
  return User;
};


如果为不同的数据源定义同一个模型,那么对于不同的数据库,同一个模型文件将执行两次,因此我们可以使用两个参数获取 sequelize 实例:


// app/model/user.js
// if this file will load multiple times for different datasource
// we can use the secound argument to get the sequelize instance
module.exports = (app, model) => {
  const { STRING, INTEGER, DATE } = app.Sequelize;
  const User = model.define('user', {
    login: STRING,
    name: STRING(30),
    password: STRING(32),
    age: INTEGER,
    last_sign_in_at: DATE,
    created_at: DATE,
    updated_at: DATE,
  });
  return User;
};


自定义 Sequelize


默认情况下,egg-sequelize 将使用 sequelize@5,您可以自定义 sequelize 版本使用 config.sequelize.Sequelize 绕过,例如:


// config/config.default.js
exports.sequelize = {
  Sequelize: require('sequelize'),
};


完整示例


// app/model/post.js
module.exports = app => {
  const { STRING, INTEGER, DATE } = app.Sequelize;
  const Post = app.model.define('Post', {
    name: STRING(30),
    user_id: INTEGER,
    created_at: DATE,
    updated_at: DATE,
  });
  Post.associate = function() {
    app.model.Post.belongsTo(app.model.User, { as: 'user' });
  }
  return Post;
};


// app/controller/post.js
class PostController extends Controller {
  async index() {
    const posts = await this.ctx.model.Post.findAll({
      attributes: [ 'id', 'user_id' ],
      include: { model: this.ctx.model.User, as: 'user' },
      where: { status: 'publish' },
      order: 'id desc',
    });
    this.ctx.body = posts;
  }
  async show() {
    const post = await this.ctx.model.Post.findByPk(this.params.id);
    const user = await post.getUser();
    post.setDataValue('user', user);
    this.ctx.body = post;
  }
  async destroy() {
    const post = await this.ctx.model.Post.findByPk(this.params.id);
    await post.destroy();
    this.ctx.body = { success: true };
  }
}


同步模型到数据库


我们强烈建议您使用 Sequelize - Migrations 创建或迁移数据库。


此代码只应在开发中使用。


// {app_root}/app.js
module.exports = app => {
  if (app.config.env === 'local' || app.config.env === 'unittest') {
    app.beforeStart(async () => {
      await app.model.sync({force: true});
    });
  }
};


相关实践学习
每个IT人都想学的“Web应用上云经典架构”实战
本实验从Web应用上云这个最基本的、最普遍的需求出发,帮助IT从业者们通过“阿里云Web应用上云解决方案”,了解一个企业级Web应用上云的常见架构,了解如何构建一个高可用、可扩展的企业级应用架构。
MySQL数据库入门学习
本课程通过最流行的开源数据库MySQL带你了解数据库的世界。   相关的阿里云产品:云数据库RDS MySQL 版 阿里云关系型数据库RDS(Relational Database Service)是一种稳定可靠、可弹性伸缩的在线数据库服务,提供容灾、备份、恢复、迁移等方面的全套解决方案,彻底解决数据库运维的烦恼。 了解产品详情: https://www.aliyun.com/product/rds/mysql 
相关文章
|
监控 测试技术
PTS日志问题之请求压测报告失败如何解决
PTS(Performance Testing Service)是一项面向网站、应用等提供的压力测试服务,用于模拟不同场景下的用户访问,评估系统的性能表现;在进行PTS压测时,可能会出现一些异常或报错,本合集将PTS压测中频繁出现的问题及其解决办法进行汇编,旨在帮助用户更有效地进行性能测试和问题定位。
|
1月前
|
缓存 JavaScript 小程序
怎样对UniApp的首屏渲染进行优化?
怎样对UniApp的首屏渲染进行优化?
340 140
|
存储 人工智能 前端开发
【利用AI让知识体系化】入门Egg框架(含实战)(二)
【利用AI让知识体系化】入门Egg框架(含实战)
|
5月前
|
开发框架 JSON 中间件
Go语言Web开发框架实践:使用 Gin 快速构建 Web 服务
Gin 是一个高效、轻量级的 Go 语言 Web 框架,支持中间件机制,非常适合开发 RESTful API。本文从安装到进阶技巧全面解析 Gin 的使用:快速入门示例(Hello Gin)、定义 RESTful 用户服务(增删改查接口实现),以及推荐实践如参数校验、中间件和路由分组等。通过对比标准库 `net/http`,Gin 提供更简洁灵活的开发体验。此外,还推荐了 GORM、Viper、Zap 等配合使用的工具库,助力高效开发。
|
8月前
|
前端开发 JavaScript
【Javascript系列】Terser除了压缩代码之外,还有优化代码的功能
Terser 是一款广泛应用于前端开发的 JavaScript 解析器和压缩工具,常被视为 Uglify-es 的替代品。它不仅能高效压缩代码体积,还能优化代码逻辑,提升可靠性。例如,在调试中发现,Terser 压缩后的代码对删除功能确认框逻辑进行了优化。常用参数包括 `compress`(启用压缩)、`mangle`(变量名混淆)和 `output`(输出配置)。更多高级用法可参考官方文档。
594 11
|
消息中间件 关系型数据库 Kafka
实时计算 Flink版产品使用合集之想要加快消费 Kafka 数据的速度,该怎么配置参数
实时计算Flink版作为一种强大的流处理和批处理统一的计算框架,广泛应用于各种需要实时数据处理和分析的场景。实时计算Flink版通常结合SQL接口、DataStream API、以及与上下游数据源和存储系统的丰富连接器,提供了一套全面的解决方案,以应对各种实时计算需求。其低延迟、高吞吐、容错性强的特点,使其成为众多企业和组织实时数据处理首选的技术平台。以下是实时计算Flink版的一些典型使用合集。
555 2
|
运维 自然语言处理 供应链
Java云HIS医院管理系统源码 病案管理、医保业务、门诊、住院、电子病历编辑器
通过门诊的申请,或者直接住院登记,通过”护士工作站“分配患者,完成后,进入医生患者列表,医生对应开具”长期医嘱“和”临时医嘱“,并在电子病历中,记录病情。病人出院时,停止长期医嘱,开具出院医嘱。进入出院审核,审核医嘱与住院通过后,病人结清缴费,完成出院。
442 4
|
12月前
|
SQL 关系型数据库 MySQL
PHP与MySQL的高效协同开发策略####
本文深入探讨了PHP与MySQL在Web开发中的协同工作机制,通过优化配置、最佳实践和高级技巧,展示了如何提升数据库交互性能,确保数据安全,并促进代码可维护性。我们将从环境搭建讲起,逐步深入到查询优化、事务管理、安全防护及性能调优等核心环节,为开发者提供一套实战驱动的解决方案框架。 ####
|
JavaScript 前端开发 开发者
JS逆向 -- 开发者工具介绍
JS逆向 -- 开发者工具介绍
143 0
|
机器学习/深度学习 分布式计算 算法
MaxCompute 的 MapReduce 与机器学习
【8月更文第31天】随着大数据时代的到来,如何有效地处理和分析海量数据成为了一个重要的课题。MapReduce 是一种编程模型,用于处理和生成大型数据集,其核心思想是将计算任务分解为可以并行处理的小任务。阿里云的 MaxCompute 是一个面向离线数据仓库的计算服务,提供了 MapReduce 接口来处理大规模数据集。本文将探讨如何利用 MaxCompute 的 MapReduce 功能来执行复杂的计算任务,特别是应用于机器学习场景。
292 0