Nestjs数据库

Nest与数据库无关,允许您轻松地与任何SQL或NoSQL数据库集成。根据您的偏好,您有许多可用的选项。一般来说,将Nest连接到数据库只需为数据库加载一个适当的Node.js驱动程序,就像使用 Express 或Fastify一样。

您还可以直接使用任何通用的Node.js数据库集成库或ORM,例如 Sequelize (recipe)、knexjs (tutorial)`和 TypeORM ,以在更高的抽象级别上进行操作。

为了方便起见,Nest还提供了与现成的TypeORM与@nestjs/typeorm的紧密集成,我们将在本章中对此进行介绍,而与@nestjs/mongoose的紧密集成将在本章中介绍。这些集成提供了附加的特定于nestjs的特性,比如模型/存储库注入、可测试性和异步配置,从而使访问您选择的数据库更加容易。

Nestjs TypeORM 集成

为了与SQL和NoSQL数据库集成,Nest提供了@nestjs/typeorm包。Nest使用TypeORM是因为它是TypeScript中最成熟的对象关系映射器(ORM)。因为它是用TypeScript编写的,所以可以很好地与Nest框架集成。

为了开始使用它,我们首先安装所需的依赖项。在本章中,我们将演示如何使用流行的 Mysql ,TypeORM提供了对许多关系数据库的支持,比如PostgreSQL、Oracle、Microsoft SQL Server、SQLite,甚至像MongoDB这样的NoSQL数据库。我们在本章中介绍的过程对于TypeORM支持的任何数据库都是相同的。您只需为所选数据库安装相关的客户端API库。

$ npm install --save @nestjs/typeorm typeorm mysql

安装过程完成后,我们可以将TypeOrmModule导入AppModule。

app.module.ts

import { Module } from '@nestjs/common';

import { TypeOrmModule } from '@nestjs/typeorm';

@Module({

imports: [

TypeOrmModule.forRoot({

type: 'mysql',

host: 'localhost',

port: 3306,

username: 'root',

password: 'root',

database: 'test',

entities: [],

synchronize: true,

export class AppModule {}

forRoot()方法接受与来自TypeORM包的createConnection()相同的配置对象。另外,我们可以创建ormconfig.json,而不是将配置对象传递给forRoot()。

"type": "mysql",

"host": "localhost",

"port": 3306,

"username": "root",

"password": "root",

"database": "test",

"entities": ["dist/**/*.entity{.ts,.js}"],

"synchronize": true

?> 静态全局路径(例如dist/**/*.entity{ .ts,.js})不适用于Webpack热重载。

然后,我们可以调用forRoot()没有任何选项:

app.module.ts

import { Module } from '@nestjs/common';

import { TypeOrmModule } from '@nestjs/typeorm';

@Module({

imports: [TypeOrmModule.forRoot()],

export class AppModule {}

一旦完成,TypeORM连接和EntityManager对象就可以在整个项目中注入(不需要导入任何模块),例如:

app.module.ts

import { Connection } from 'typeorm';

@Module({

imports: [TypeOrmModule.forRoot(), PhotoModule],

export class AppModule {

constructor(private readonly connection: Connection) {}

存储库模式

TypeORM支持存储库设计模式,因此每个实体都有自己的存储库。可以从数据库连接获得这些存储库。

为了继续这个示例,我们需要至少一个实体。我们将使用官方TypeORM文档中的Photo实体。

photo/photo.entity.ts

import { Entity, Column, PrimaryGeneratedColumn } from 'typeorm';

@Entity()

export class Photo {

@PrimaryGeneratedColumn()

id: number;

@Column({ length: 500 })

name: string;

@Column('text')

description: string;

@Column()

filename: string;

@Column('int')

views: number;

@Column()

isPublished: boolean;

该Photo实体属于该photo目录。这个目录代表了PhotoModule。这是你决定在哪里保留你的模型文件。从我的观点来看,最好的方法是将它们放在他们的域中, 放在相应的模块目录中。

开始使用photo实体,我们需要让TypeORM知道它插入实体数组:

app.module.ts

import { Module } from '@nestjs/common';

import { TypeOrmModule } from '@nestjs/typeorm';

import { Photo } from './photo/photo.entity';

@Module({

imports: [

TypeOrmModule.forRoot({

type: 'mysql',

host: 'localhost',

port: 3306,

username: 'root',

password: 'root',

database: 'test',

entities: [Photo],

synchronize: true,

export class AppModule {}

现在让我们看一下PhotoModule:

photo.module.ts

import { Module } from '@nestjs/common';

import { TypeOrmModule } from '@nestjs/typeorm';

import { PhotoService } from './photo.service';

import { PhotoController } from './photo.controller';

import { Photo } from './photo.entity';

@Module({

imports: [TypeOrmModule.forFeature([Photo])],

providers: [PhotoService],

controllers: [PhotoController],

export class PhotoModule {}

此模块使用forFeature()方法定义在当前范围中注册哪些存储库。这样,我们就可以使用@InjectRepository()装饰器将PhotoRepository注入到PhotoService中:

photo.service.ts

import { Injectable } from '@nestjs/common';

import { InjectRepository } from '@nestjs/typeorm';

import { Repository } from 'typeorm';

import { Photo } from './photo.entity';

@Injectable()

export class PhotoService {

constructor(

@InjectRepository(Photo)

private readonly photoRepository: Repository,

findAll(): Promise {

return this.photoRepository.find();

?> 不要忘记将PhotoModule导入根ApplicationModule。

如果要在导入TypeOrmModule.forFeature的模块之外使用存储库,则需要重新导出由其生成的提供程序。 您可以通过导出整个模块来做到这一点,如下所示:

photo.module.ts

import { Module } from '@nestjs/common';

import { TypeOrmModule } from '@nestjs/typeorm';

import { Photo } from './photo.entity';

@Module({

imports: [TypeOrmModule.forFeature([Photo])],

exports: [TypeOrmModule]

export class PhotoModule {}

现在,如果我们在PhotoHttpModule中导入PhotoModule,我们可以在后一个模块的提供者中使用@InjectRepository(Photo)。

photo-http.module.ts

import { Module } from '@nestjs/common';

import { PhotoModule } from './photo.module';

import { PhotoService } from './photo.service';

import { PhotoController } from './photo.controller';

@Module({

imports: [PhotoModule],

providers: [PhotoService],

controllers: [PhotoController]

export class PhotoHttpModule {}

多个数据库

某些项目可能需要多个数据库连接。幸运的是,这也可以通过本模块实现。要使用多个连接,首先要做的是创建这些连接。在这种情况下,连接命名成为必填项。

假设你有一个Person实体和一个Album实体,每个实体都存储在他们自己的数据库中。

const defaultOptions = {

type: 'postgres',

port: 5432,

username: 'user',

password: 'password',

database: 'db',

synchronize: true,

@Module({

imports: [

TypeOrmModule.forRoot({

...defaultOptions,

host: 'photo_db_host',

entities: [Photo],

TypeOrmModule.forRoot({

...defaultOptions,

name: 'personsConnection',

host: 'person_db_host',

entities: [Person],

TypeOrmModule.forRoot({

...defaultOptions,

name: 'albumsConnection',

host: 'album_db_host',

entities: [Album],

export class AppModule {}

?> 如果未为连接设置任何name,则该连接的名称将设置为default。请注意,不应该有多个没有名称或同名的连接,否则它们会被覆盖。

此时,您的Photo、Person和Album实体中的每一个都已在各自的连接中注册。通过此设置,您必须告诉TypeOrmModule.forFeature()函数和@InjectRepository()装饰器应该使用哪种连接。如果不传递任何连接名称,则使用default连接。

@Module({

imports: [

TypeOrmModule.forFeature([Photo]),

TypeOrmModule.forFeature([Person], 'personsConnection'),

TypeOrmModule.forFeature([Album], 'albumsConnection'),

export class AppModule {}

您也可以为给定的连接注入Connection或EntityManager:

@Injectable()

export class PersonService {

constructor(

@InjectConnection('personsConnection')

private readonly connection: Connection,

@InjectEntityManager('personsConnection')

private readonly entityManager: EntityManager,

在单元测试我们的应用程序时,我们通常希望避免任何数据库连接,从而使我们的测试适合于独立,并使它们的执行过程尽可能快。但是我们的类可能依赖于从连接实例中提取的存储库。那是什么?解决方案是创建假存储库。为了实现这一点,我们设置了自定义提供者。事实上,每个注册的存储库都由entitynamereposition标记表示,其中EntityName是实体类的名称。

@nestjs/typeorm包提供了基于给定实体返回准备好token的getRepositoryToken()函数。

@Module({

providers: [

PhotoService,

provide: getRepositoryToken(Photo),

useValue: mockRepository,

export class PhotoModule {}

现在, 将使用硬编码mockRepository作为PhotoRepository。每当任何提供程序使用@InjectRepository()装饰器请求PhotoRepository时,Nest会使用注册的mockRepository对象。

定制存储库

TypeORM提供称为自定义存储库的功能。要了解有关它的更多信息,请访问此页面。基本上,自定义存储库允许您扩展基本存储库类,并使用几种特殊方法对其进行丰富。

要创建自定义存储库,请使用@EntityRepository()装饰器和扩展Repository类。

@EntityRepository(Author)

export class AuthorRepository extends Repository {}

?>@EntityRepository()和Repository来自typeorm包。

创建类后,下一步是将实例化责任移交给Nest。为此,我们必须将AuthorRepository类传递给TypeOrm.forFeature()函数。

@Module({

imports: [TypeOrmModule.forFeature([AuthorRepository])],

controller: [AuthorController],

providers: [AuthorService],

export class AuthorModule {}

之后,只需使用以下构造注入存储库:

@Injectable()

export class AuthorService {

constructor(private readonly authorRepository: AuthorRepository) {}

通常,您可能希望异步传递模块选项,而不是事先传递它们。在这种情况下,使用forRootAsync()函数,提供了几种处理异步数据的方法。

第一种可能的方法是使用工厂函数:

TypeOrmModule.forRootAsync({

useFactory: () => ({

type: 'mysql',

host: 'localhost',

port: 3306,

username: 'root',

password: 'root',

database: 'test',

entities: [__dirname + '/**/*.entity{.ts,.js}'],

synchronize: true,

我们的工厂的行为与任何其他异步提供者一样(例如,它可以是异步的,并且它能够通过注入注入依赖)。

TypeOrmModule.forRootAsync({

imports: [ConfigModule],

useFactory: async (configService: ConfigService) => ({

type: 'mysql',

host: configService.getString('HOST'),

port: configService.getString('PORT'),

username: configService.getString('USERNAME'),

password: configService.getString('PASSWORD'),

database: configService.getString('DATABASE'),

entities: [__dirname + '/**/*.entity{.ts,.js}'],

synchronize: true,

inject: [ConfigService],

或者,您可以使用类而不是工厂。

TypeOrmModule.forRootAsync({

useClass: TypeOrmConfigService,

上面的构造将TypeOrmConfigService在内部进行实例化TypeOrmModule,并将利用它来创建选项对象。在TypeOrmConfigService必须实现TypeOrmOptionsFactory的接口。

@Injectable()

class TypeOrmConfigService implements TypeOrmOptionsFactory {

createTypeOrmOptions(): TypeOrmModuleOptions {

return {

type: 'mysql',

host: 'localhost',

port: 3306,

username: 'root',

password: 'root',

database: 'test',

entities: [__dirname + '/**/*.entity{.ts,.js}'],

synchronize: true,

为了防止在TypeOrmModule中创建TypeOrmConfigService并使用从不同模块导入的提供程序,可以使用useExisting语法。

TypeOrmModule.forRootAsync({

imports: [ConfigModule],

useExisting: ConfigService,

这个构造与useClass的工作原理相同,但有一个关键的区别 —TypeOrmModule将查找导入的模块来重用现有的ConfigService,而不是实例化一个新的ConfigService。

这儿有一个可用的例子。

Nestjs数据库Nest与数据库无关,允许您轻松地与任何SQL或NoSQL数据库集成。根据您的偏好,您有许多可用的选项。一般来说,将Nest连接到数据库只需为数据库加载一个适当的Node.js驱动程序,就像使用 Express 或Fastify一样。您还可以直接使用任何通用的Node.js数据库集成库或ORM,例如 Sequelize (recipe)、knexjs (tutorial)`和 T...
原项目地址: 一、项目介绍 1、采用java的MVC的经典开发模型(在 nestjs 开发中也可以使用基于angular方式的模块化开发模式,看个人喜好),来构建项目结构,也符合后端企业开发的需求。 2、项目是基于 mysql 数据库 开发的 3、使用jwt的方式进行登录鉴权(颗粒度仅到菜单权限) 二、使用项目 1、本项目仅仅是实现了rbac的权限系统,对于其他的功能需要自己基于这个基础上去扩展 2、先在本地创建 数据库 3、在项目的根目录的.env文件修改为你自己的 数据库 基本 配置 (地址、用户名、密码、 数据库 ) 4、启动项目 npm run start:dev 5、运行第五步的时候会默认初始化菜单数据和用户数据(账号:admin,密码:123456) 6、如果你想初始化别的数据,可以在src/services/init-db中写上你要初始化的数据 二、主要实现功能 实现用户的登录、jwt鉴权
之前已经了解过了官方的hello-world项目了,对项目的总体结构也已经有了大体的认识,接下来开始研究连接 数据库 操作 。 nest.js 本身内置了 TypeORM 数据库 处理模块,它为许多不同的 数据库 提供了支持,现在我们以 MySQL 为例子,项目本身还是用的官方的hello-world项目 首先 数据库 电脑自己安装好 mysql 然后用连接工具(我使用的navicat)可以连接 然后我...
官方API(点击跳转) 1.安装(和官方一样使用 mysql ,其它 数据库 请安装其它的依赖包) npm install typeorm reflect-metadata @types/node mysql --save 2.TypeScript编译器版本3.3或更高版本,并且您...
npm install cache-manager npm install -D @types/cache-manager npm install cache-manager-redis-store --save 二、redis-cache.service.ts import { Injectable, CACHE_MANAGER, Inject } from '@ nestjs /common'; import { Cache } fro. 全网最新的使用ts的sequelize教程 TypeORM 是一个ORM框架,可以与 TS 和 JS(ES5,ES6,ES7,ES8)一起使用。 它的目标是始终支持最新的 JS 特性并提供额外的特性以帮助你开发任何使用 数据库 的应用程序 Sequelize 是一个基于 promise 的 Node.js ORM, 目前支持 Postgres, MySQL , MariaDB, SQLite 以及 Microsoft SQL Se
文档:https://docs. nestjs .com/techniques/databaseNest 与 数据库 无关,可以轻松与任何 SQL 或 NoSQL 数据库 集成。可以直接使用任何通用的 Node.js 数据集成库或 ORM,如Nest 提供了与 TypeORM 和 Sequelize 的紧密集成,分别使用要开始使用它,首先安装所需的依赖项。 安装完成后,把 TypeOrm Module导入到 AppModule中。 不应在生产中使用 synchronize: true 设置,否则可能会丢失生产数据