Midway 集成 Sequelize 完整实战指南:从安装配置到 CRUD 与多数据源管理

发布时间:2026/10/8 14:08:27
Midway 集成 Sequelize 完整实战指南:从安装配置到 CRUD 与多数据源管理 后端微服务云原生【免费下载链接】midway A Node.js Serverless Framework for front-end/full-stack developers. Build the application for next decade. Works on AWS, Alibaba Cloud, Tencent Cloud and traditional VM/Container. Super easy integrate with React and Vue. 项目地址https://gitcode.com/gh_mirrors/mi/midway点击查看免费下载本文档讲解的是 Midway 生态中midwayjs/sequelize组件的使用方式面向需要在 Midway 项目中接入关系型数据库MySQL、PostgreSQL、SQLite、SQL Server 等的开发者。读完本文你将掌握 Sequelize 组件的安装、数据源配置、实体Entity定义、增删查改、联合查询与连表查询的完整写法并理解组件底层的数据源管理机制能够在标准项目、Serverless 与一体化项目中直接落地。:::tip 本文档对应的完整原始说明见 site/docs/legacy/sequelize.md。该组件文档自 v3.4.0 版本起标记为废弃但组件本身仍随 Midway 维护发行当前仓库中midwayjs/sequelize的版本为 4.2.5见 packages/sequelize/package.json搭配sequelize6.x 与sequelize-typescript2.x 使用本文基于当前仓库源码与实测用例编写用法依然成立。 :::一、组件能力与适用场景midwayjs/sequelize是 Midway 官方维护的 Sequelize 集成组件其核心价值在于把 Sequelize 的实例纳入 Midway 的依赖注入IoC体系与生命周期管理无需手动维护连接实例的创建与销毁基于 Midway 通用的DataSourceManager抽象实现多数据源管理一个应用可同时连接多个数据库提供InjectRepository、InjectDataSource两个自定义属性装饰器让实体仓储Repository和数据源以声明式方式注入到任意业务类中支持sync自动建表、entities批量注册模型等便利配置降低接入成本。描述说明可用于标准项目✅可用于 Serverless✅可用于一体化前后端一体✅二、安装与依赖在项目根目录执行$ npm i midwayjs/sequelize4 sequelize --save或者在package.json中手动增加如下依赖后重新安装{ dependencies: { midwayjs/sequelize: ^4.0.0, sequelize: ^6.13.0 // ... }, devDependencies: { // ... } }从当前仓库 packages/sequelize/package.json 可以看到组件内部基于sequelize-typescript2.1.6提供 TypeScript 装饰器能力Node 运行环境要求20。组件自身依赖midwayjs/core的DataSourceManager、MidwayDecoratorService等基础设施因此无需额外安装其他 Midway 模块。三、安装数据库 DriverSequelize 本身不携带具体数据库驱动需要根据目标数据库单独安装。常用驱动如下# for MySQL or MariaDB也可以使用 mysql2 替代 npm install mysql --save npm install mysql2 --save # for PostgreSQL or CockroachDB npm install pg --save # for SQLite npm install sqlite3 --save # for Microsoft SQL Server npm install mssql --save # for sql.js npm install sql.js --save # for Oracle npm install oracledb --save # for MongoDB(experimental) npm install mongodb --save当前仓库的组件测试即使用sqlite3作为内存/本地文件数据库来跑用例见 packages/sequelize/test/fixtures/sequelize-new/src/config/config.default.ts因此即使没有外部数据库服务也可以先通过 SQLite 快速验证组件能力。四、引入组件模块在src/configuration.ts中通过imports引入组件import { App, Configuration, ILifeCycle } from midwayjs/core; import { Application } from midwayjs/web; import { join } from path; import * as sequelize from midwayjs/sequelize; Configuration({ imports: [sequelize], importConfigs: [join(__dirname, ./config)], }) export class MainConfiguration implements ILifeCycle { App() app: Application; async onReady() {} }组件入口文件 packages/sequelize/src/index.ts 对外导出Configuration、InjectRepository、InjectDataSource、SequelizeDataSourceManager以及配置类型SequelizeConfigOptions引入后即可在业务代码中按需使用。五、数据源配置在src/config/config.default.ts中配置// src/config/config.default.ts export default { // ... sequelize: { dataSource: { default: { database: test4, username: root, password: 123456, host: 127.0.0.1, // 此处支持 idb 上面 vipserver key 的那种方式也支持 aliyun 的地址。 port: 3306, encrypt: false, dialect: mysql, define: { charset: utf8 }, timezone: 08:00, logging: console.log, }, }, sync: false, // 本地的时候可以通过 sync: true 直接 createTable }, };5.1 配置结构解析配置的根键为sequelize内部结构对应 packages/sequelize/src/interface.ts 中定义的SequelizeConfigOptions即DataSourceManagerConfigOptionSequelizeOptions。核心字段说明配置项类型说明dataSourceRecordstring, SequelizeOptions数据源集合key 为数据源名称如default、customvalue 为传给new Sequelize(options)的连接选项defaultDataSourceNamestring指定默认数据源名称未指定时取dataSource的第一个 key详见下方源码说明syncboolean连接成功后是否自动同步建表等价于执行client.sync()本地开发设为true即可自动createTablesyncOptionsobject传给client.sync()的选项如force、alter等配合sync: true使用entitiesModel[]注册到该数据源的模型类数组创建数据源时会调用client.addModels(entities)单个数据源的连接选项直接透传给 Sequelizedialect、host、port、database、username、password、timezone、logging、define等均为 Sequelize 原生支持的字段例如dialectmysql|postgres|sqlite|mssql等storageSQLite 场景下指定数据库文件路径timezone: 08:00统一数据库连接时区logging: console.log打印执行的 SQL 日志便于排查define: { charset: utf8 }为表定义设置默认字符集。5.2 从源码看数据源创建流程组件在 packages/sequelize/src/dataSourceManager.ts 中实现SequelizeDataSourceManager它继承自 Midway core 的DataSourceManagerSequelize其createDataSource方法的核心逻辑是从配置中拆出customDataSourceClass若存在则用它构造客户端否则new Sequelize(otherConfig)读取config[entities]若存在则调用client.addModels(entities)批量注册模型调用checkConnected内部执行authenticate()验证连接若连接成功且配置了sync则执行client.sync(config.syncOptions)自动建表。组件在 packages/sequelize/src/configuration.ts 中注册了两个自定义属性装饰器处理逻辑InjectRepository对应ENTITY_MODEL_KEY按connectionName或模型归属数据源解析返回dataSource.getRepository(modelKey)InjectDataSource对应DATA_SOURCE_KEY按数据源名称返回对应的 Sequelize 实例。同时SequelizeConfiguration的onStop钩子会在应用关闭时调用dataSourceManager.stop()统一释放连接池无需开发者手工close()。5.3 连接验证与失败策略checkConnected通过authenticate()探测连接失败时仅记录错误并返回false此时不会抛错中断应用。是否把连接失败升级为致命错误取决于组件DataSourceManager的validateConnection配置。仓库测试 packages/sequelize/test/index.test.ts 中有两个对照用例validateConnection: false时即使连接失败客户端对象也能创建成功manager.getAllDataSources().size为 1validateConnection: true时连接失败会抛出MidwayCommonError。生产环境建议开启validateConnection以便快速暴露数据库不可用的问题本地调试时可关闭以容忍暂时无法连接。六、定义业务层 Entity6.1 定义 Entity带关联关系组件推荐使用sequelize-typescript的装饰器语法定义模型。以下示例中Photo通过外键关联Userimport { Column, Model, BelongsTo, ForeignKey } from sequelize-typescript; import { BaseTable } from midwayjs/sequelize; import { User } from ./User; BaseTable export class Photo extends Model { ForeignKey(() User) Column({ comment: 用户Id, }) userId: number; BelongsTo(() User) user: User; Column({ comment: 名字, }) name: string; }import { Model, Column, HasMany } from sequelize-typescript; import { BaseTable } from midwayjs/sequelize; import { Photo } from ./Photo; BaseTable export class User extends Model { Column name!: string; HasMany(() Photo) Photo: Photo[]; }说明BaseTable是组件对外暴露的模型基类装饰器由midwayjs/sequelize导出用于把普通Model类纳入数据源的模型管理Column声明字段comment会写入建表语句ForeignKey(() User)、BelongsTo(() User)、HasMany(() Photo)声明一对多/多对一关联为后续连表查询提供元数据。6.2 通过 entities 注册模型定义好的模型需要在数据源配置中显式注册组件才会调用addModels完成加载。例如仓库 fixture 中的写法packages/sequelize/test/fixtures/sequelize-new/src/config/config.default.tsimport { HelloModel } from ../model/hello; import { UserModel } from ../model/user; export const sequelize { dataSource: { custom: { dialect: sqlite, storage: path.join(__dirname, ../../, database.sqlite), sync: true, entities: [HelloModel, UserModel], }, }, defaultDataSourceName: custom, };其中defaultDataSourceName: custom显式指定默认数据源与 packages/sequelize/src/configuration.ts 中getDefaultDataSourceName()的取值逻辑相呼应。七、在业务代码中使用 Entity 进行 CRUD7.1 查询列表import { Config, Controller, Get, Provide } from midwayjs/core; import { Photo } from ../entity/Photo; Provide() Controller(/) export class HomeController { Get(/) async home() { let result await Photo.findAll(); console.log(result); return hello world; } }7.2 增加数据import { Controller, Post, Provide } from midwayjs/core; import { Photo } from ../entity/Photo; Provide() Controller(/) export class HomeController { Post(/add) async home() { let result await Photo.create({ name: 123, }); console.log(result); return hello world; } }7.3 删除数据import { Controller, Post, Provide } from midwayjs/core; import { Photo } from ../entity/Photo; Provide() Controller(/) export class HomeController { Post(/delete) async home() { await Photo.destroy({ where: { name: 123, }, }); return hello world; } }7.4 查找单个import { Controller, Post, Provide } from midwayjs/core; import { Photo } from ../entity/Photo; Provide() Controller(/) export class HomeController { Post(/delete) async home() { let result await Photo.findOne({ where: { name: 123, }, }); return hello world; } }7.5 联合查询Op 操作符import { Controller, Get, Provide } from midwayjs/core; import { Photo } from ../entity/Photo; import { Op } from sequelize; Provide() Controller(/) export class HomeController { Get(/) async home() { // SELECT * FROM photo WHERE name 23 OR name 34; let result await Photo.findAll({ where: { [Op.or]: [{ name: 23 }, { name: 34 }], }, }); console.log(result); return hello world; } }Op是 Sequelize 内置的符号操作符集合除Op.or外还包含Op.and、Op.ne、Op.gt、Op.lt、Op.in、Op.like、Op.between等可用于构造各种复杂的查询条件。需要更完整的操作符用法时可查阅 Sequelize 官方关于查询querying的文档章节。7.6 连表查询import { Controller, Get, Provide } from midwayjs/core; import { User } from ../entity/User; import { Photo } from ../entity/Photo; Provide() Controller(/users) export class HomeController { Get(/) async home() { let result await User.findAll({ include: [Photo] }); console.log(result); return hello world; } }include数组中的模型必须与实体上声明的HasMany/BelongsTo关联元数据对应Sequelize 会根据关联自动生成 JOIN 语句并填充关联数据。7.7 复杂场景使用 Raw Query对于多表聚合、复杂统计等难以用 ORM 表达的场景可以使用 Sequelize 的原始查询raw queries能力通过sequelize.query(sql)直接执行 SQL 语句并返回结果。在多数据源场景下可以结合InjectDataSource()注入指定数据源实例后调用import { Controller, Get, Provide, Inject } from midwayjs/core; import { InjectDataSource } from midwayjs/sequelize; import { Sequelize } from sequelize-typescript; Provide() Controller(/) export class HomeController { InjectDataSource(default) sequelize: Sequelize; Get(/raw) async raw() { const [results] await this.sequelize.query( SELECT * FROM photo WHERE name ?, { replacements: [123] } ); return results; } }八、推荐的 Service 层注入写法与测试验证尽管控制器中可以直接调用静态模型方法组件更推荐在 Service 层通过InjectRepository注入仓储Repository这样既能享受依赖注入管理也便于单元测试。仓库测试 fixture packages/sequelize/test/fixtures/sequelize-new/src/service/user.ts 给出了标准写法import { Provide } from midwayjs/core; import { Repository } from sequelize-typescript; import { HelloModel } from ../model/hello; import { UserModel } from ../model/user; import { InjectRepository } from midwayjs/sequelize; Provide() export class UserService { InjectRepository(UserModel) userRepository: RepositoryUserModel; InjectRepository(HelloModel) helloRepository: RepositoryHelloModel; async list() { return this.userRepository.findAll(); } async add() { return this.userRepository.create({ name: 123 }); } async delete() { await this.userRepository.destroy({ where: { name: 123 } }); } }对应模型定义packages/sequelize/test/fixtures/sequelize-new/src/model/user.tsimport { Column, Model, Table } from sequelize-typescript; Table export class UserModel extends Model { Column({ comment: 名字, }) name: string; }仓库集成测试 packages/sequelize/test/index.test.ts 完整验证了以下流程通过createLegacyLightApp加载 fixture 应用使用 SQLite 落盘文件database.sqlitelist/listHello初始返回空列表add后列表长度变为 1且InjectRepository注入的仓储与直接调用模型静态方法listWithModel结果一致delete后列表恢复为空。这套测试证明InjectRepository注入的仓储与Model.findAll静态调用在语义上完全等价开发者可以按团队习惯任选其一或者统一使用注入式写法以获得更好的可测试性。九、多数据源与数据源注入在微服务或读写分离场景下dataSource可以配置多个数据源例如// src/config/config.default.ts export default { sequelize: { dataSource: { default: { dialect: mysql, host: 127.0.0.1, port: 3306, database: app_main, username: root, password: 123456, entities: [UserModel], }, report: { dialect: mysql, host: 127.0.0.1, port: 3306, database: app_report, username: root, password: 123456, entities: [ReportModel], }, }, defaultDataSourceName: default, }, };组件通过InjectRepository的第二个参数指定数据源通过InjectDataSource直接注入数据源实例import { Provide } from midwayjs/core; import { InjectDataSource, InjectRepository } from midwayjs/sequelize; import { Sequelize } from sequelize-typescript; import { ReportModel } from ../model/report; Provide() export class ReportService { InjectRepository(ReportModel, report) reportRepository; InjectDataSource(report) reportDataSource: Sequelize; }从 packages/sequelize/src/configuration.ts 的注入解析逻辑可以看到InjectRepository的数据源选择优先级为显式connectionName 模型注册归属的数据源 默认数据源InjectDataSource则支持直接指定数据源名称不指定时回退到默认数据源。这一机制让多数据源场景下的模型与连接管理保持清晰可控。十、生命周期与资源释放组件完全托管了 Sequelize 客户端的生命周期启动阶段SequelizeConfiguration.onReady从容器获取SequelizeDataSourceManager后者在Init阶段以并发方式初始化全部数据源运行阶段所有数据源均为单例ScopeEnum.Singleton通过依赖注入共享同一连接池关闭阶段应用销毁时onStop调用dataSourceManager.stop()逐一close()所有数据源。因此开发者无需也不建议在业务代码中自行创建或关闭 Sequelize 实例只需专注定义模型与编写业务逻辑。小结本文从安装、驱动选择、模块引入、数据源配置入手完整覆盖了midwayjs/sequelize在 Midway 中的标准接入流程并给出了 Entity 定义、CRUD、联合查询、连表查询、Raw Query、Service 注入与多数据源管理的完整示例。其中数据源创建、模型注册、连接验证与装饰器注入的机制均可在 packages/sequelize/src 的源码及 packages/sequelize/test 的测试用例中得到印证。对于 Sequelize 自身的查询操作符、原始 SQL 等更细粒度的能力建议以 Sequelize 官方文档为准本文侧重说明其在 Midway 框架内的集成与使用姿势。赞分享后端微服务云原生【免费下载链接】midway A Node.js Serverless Framework for front-end/full-stack developers. Build the application for next decade. Works on AWS, Alibaba Cloud, Tencent Cloud and traditional VM/Container. Super easy integrate with React and Vue. 项目地址https://gitcode.com/gh_mirrors/mi/midway点击查看免费下载相关推荐Midway 集成 Leoric ORM 组件从配置到源码级的数据源管理实战指南Midway 集成 Leoric ORM 组件从配置到源码级的数据源管理实战指南 midwayjs/leoric 是 Midway 官方提供的 Leoric后端微服务云原生Midway 集成 TypeORM 实战指南从数据源配置到实体模型注入Midway 集成 TypeORM 实战指南从数据源配置到实体模型注入 导读 midwayjs/typeorm 是 Midway 官方提供的 TypeORM后端微服务云原生Midway Apollo GraphQL 组件完整实战指南从安装配置到 Resolver 类与订阅Midway Apollo GraphQL 组件完整实战指南从安装配置到 Resolver 类与订阅 Apollo GraphQL 是 Midway 生态中让后端微服务云原生上一篇FanControl为什么这款开源工具能让你彻底掌控Windows风扇下一篇Mask2Former快速上手终极指南从零开始的通用图像分割实战创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

关于本文作者

来自尧图内容编辑团队

尧图内容编辑团队 内容团队

尧图内容编辑团队

本文由尧图网络内容编辑团队执笔。团队由资深项目经理、前端工程师与设计师组成,所有内容均来自亲手交付的真实项目,先讲清问题、再给出可落地的解法。尧图深耕北京网站建设十年,服务过京华建材集团、智造科技等各行业客户,把一线经验沉淀为可复用的行业观察。

  • 十年建站经验,覆盖建材、制造、服务、文创等
  • 项目经理把关选题与事实准确性
  • 工程师与设计师联合撰写专业细节
  • 统一编辑规范,保证文风与排版一致
  • 每月复盘转化数据,迭代选题方向

延伸阅读

相关资讯与近期热门内容

深度阅读推荐

建站决策前值得细读的三篇

网站改版的5个关键决策
2024-08-12

网站改版的5个关键决策

什么时候该改版、改到什么程度、如何避免流量掉光,京华建材集团改版复盘给出答案。

获取专属建站方案

看完文章,把您的行业与预算告诉我们,免费获取一份量身定制的官网建设方案与报价。

立即免费咨询