ThinkChat2.0新版上线,更智能更精彩,支持会话、画图、阅读、搜索等,送10W Token,即刻开启你的AI之旅 广告
## Sequelize ### SQL (Sequelize) 本章仅适用于 `TypeScript` > 在本文中,您将学习如何使用自定义提供者机制从零开始创建基于 **Sequelize** 包的 `DatabaseModule`。由于该解决方案包含许多开销,因此您可以使用开箱即用的 `@nestjs/sequelize` 软件包。要了解更多信息,请参阅 [此处](https://docs.nestjs.com/techniques/database#sequelize-integration)。 `Sequelize` 是一个用普通 `JavaScript` 编写的流行对象关系映射器( `ORM` ),但是有一个 `Sequelize-TypeScript` 包装器,它为基本 `Sequelize` 提供了一组装饰器和其他附加功能。 ### 入门 要开始使用这个库,我们必须安装以下附件: ```bash $ npm install --save sequelize sequelize-typescript mysql2 $ npm install --save-dev @types/sequelize ``` 我们需要做的第一步是创建一个 `Sequelize` 实例,并将一个 `options` 对象传递给构造函数。另外,我们需要添加所有模型(替代方法是使用 `modelPaths` 属性)并同步数据库表。 > database.providers.ts ```typescript import { Sequelize } from 'sequelize-typescript'; import { Cat } from '../cats/cat.entity'; export const databaseProviders = [ { provide: 'SEQUELIZE', useFactory: async () => { const sequelize = new Sequelize({ dialect: 'mysql', host: 'localhost', port: 3306, username: 'root', password: 'password', database: 'nest', }); sequelize.addModels([Cat]); await sequelize.sync(); return sequelize; }, }, ]; ``` > 按照最佳实践,我们在分隔的文件中声明了带有 `*.providers.ts` 后缀的自定义提供程序。 然后,我们需要导出这些提供程序,使它们可用于应用程序的其他部分。 ```typescript import { Module } from '@nestjs/common'; import { databaseProviders } from './database.providers'; @Module({ providers: [...databaseProviders], exports: [...databaseProviders], }) export class DatabaseModule {} ``` 现在我们可以使用 `@Inject()` 装饰器注入 `Sequelize` 对象。 每个将依赖于 `Sequelize` 异步提供程序的类将等待 `Promise` 被解析。 ### 模型注入 在 `Sequelize` 中,模型在数据库中定义了一个表。该类的实例表示数据库行。首先,我们至少需要一个实体: > cat.entity.ts ```typescript import { Table, Column, Model } from 'sequelize-typescript'; @Table export class Cat extends Model<Cat> { @Column name: string; @Column age: number; @Column breed: string; } ``` `Cat` 实体属于 `cats` 目录。 此目录代表 `CatsModule` 。 现在是时候创建一个存储库提供程序了: > cats.providers.ts ```typescript import { Cat } from './cat.entity'; export const catsProviders = [ { provide: 'CATS_REPOSITORY', useValue: Cat, }, ]; ``` ?> 在实际应用中,应避免使用魔术字符串。 `CATS_REPOSITORY` 和 `SEQUELIZE` 都应保存在单独的 `constants.ts` 文件中。 在 `Sequelize` 中,我们使用静态方法来操作数据,因此我们在这里创建了一个别名。 现在我们可以使用 `@Inject()` 装饰器将 `CATS_REPOSITORY` 注入到 `CatsService` 中: > cats.service.ts ```typescript import { Injectable, Inject } from '@nestjs/common'; import { CreateCatDto } from './dto/create-cat.dto'; import { Cat } from './cat.entity'; @Injectable() export class CatsService { constructor( @Inject('CATS_REPOSITORY') private readonly CATS_REPOSITORY: typeof Cat) {} async findAll(): Promise<Cat[]> { return this.catsRepository.findAll<Cat>(); } } ``` 数据库连接是异步的,但是 `Nest` 使此过程对于最终用户完全不可见。 `CATS_REPOSITORY` 提供程序正在等待数据库连接,并且 `CatsService` 将延迟,直到准备好使用存储库为止。 实例化每个类时,启动整个应用程序。 这是最终的 `CatsModule`: > cats.module.ts ```typescript import { Module } from '@nestjs/common'; import { CatsController } from './cats.controller'; import { CatsService } from './cats.service'; import { catsProviders } from './cats.providers'; import { DatabaseModule } from '../database/database.module'; @Module({ imports: [DatabaseModule], controllers: [CatsController], providers: [ CatsService, ...catsProviders, ], }) export class CatsModule {} ``` > 不要忘记将 `CatsModule` 导入到根 `ApplicationModule` 中。