Nest 与数据库无关,使您可以轻松地与任何 SQL 或 NoSQL 数据库集成。根据您的喜好,您有多种选择。在最一般的层面上,将 Nest 连接到数据库只是为数据库加载适当的 Node.js 驱动程序的问题,就像使用 Express 或 Fastify 一样。您还可以直接使用任何通用的 Node.js 数据库集成库或 ORM,例如 MikroORM(参见 MikroORM 配方)、Sequelize(参见 Sequelize 集成)、Knex.js(参见 Knex.js 教程)、TypeORM 和 Prisma(参见Prisma recipe),以在更高的抽象层次上运行。
为了方便起见,Nest 提供了与 TypeORM 的紧密集成,开箱即用的 Sequelize 分别使用 @nestjs/typeorm 和 @nestjs/sequelize 包,我们将在本章中介绍,Mongoose 与 @nestjs/mongoose,本章将对此进行介绍。这些集成提供了额外的 NestJS 特定功能,例如模型/存储库注入、可测试性和异步配置,使访问您选择的数据库更加容易。
为了与 SQL 和 NoSQL 数据库集成,Nest 提供了 @nestjs/typeorm 包。 Nest 使用 TypeORM,因为它是可用于 TypeScript 的最成熟的对象关系映射器 (ORM)。由于它是用 TypeScript 编写的,因此可以很好地与 Nest 框架集成。
要开始使用它,我们首先安装所需的依赖项。在本章中,我们将演示使用流行的 MySQL 关系型 DBMS,但 TypeORM 提供对许多关系型数据库的支持,例如 PostgreSQL、Oracle、Microsoft SQL Server、SQLite,甚至像 MongoDB 这样的 NoSQL 数据库。我们在本章中完成的过程对于 TypeORM 支持的任何数据库都是相同的。您只需为所选数据库安装关联的客户端 API 库。
$ npm install --save @nestjs/typeorm typeorm mysql2 // for mysql $ npm install --save @nestjs/typeorm typeorm pg // for postgre
app.module.tsJS
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 {}也可以异步加载
TypeOrmModule.forRootAsync({
imports: [ConfigModule],
inject: [ConfigService],
useFactory: (configService: ConfigService) => ({
type: 'mysql',
host: configService.get('HOST'),
port: +configService.get('PORT'),
username: configService.get('USERNAME'),
password: configService.get('PASSWORD'),
database: configService.get('DATABASE'),
entities: [],
synchronize: true,
}),
});具体可选配置参数在这里。
完成后,TypeORM DataSource 和 EntityManager 对象将可用于在整个项目中注入(无需导入任何模块)。
user.entity.ts
import { Entity, Column, PrimaryGeneratedColumn } from 'typeorm';
@Entity()
export class User {
@PrimaryGeneratedColumn()
id: number;
@Column()
firstName: string;
@Column()
lastName: string;
@Column({ default: true })
isActive: boolean;
}用户实体文件位于用户目录中。该目录包含与 UsersModule 相关的所有文件。可以决定将模型文件保存在何处,还是建议在相应的模块目录中的域附近创建它们。
要开始使用 User 实体,我们需要通过将其插入模块 forRoot() 方法选项中的实体数组来让 TypeORM 知道它(除非您使用静态 glob 路径):
TypeOrmModule.forRoot({
type: 'mysql',
host: 'localhost',
port: 3306,
username: 'root',
password: 'root',
database: 'test',
entities: [User], // 手动指定实体,或者使用自动加载autoLoadEntities
synchronize: true,
}),users.module.ts
import { Module } from '@nestjs/common';
import { TypeOrmModule } from '@nestjs/typeorm';
import { UsersService } from './users.service';
import { UsersController } from './users.controller';
import { User } from './user.entity';
@Module({
imports: [TypeOrmModule.forFeature([User])],
providers: [UsersService],
controllers: [UsersController],
})
export class UsersModule {}该模块使用 forFeature() 方法来定义在当前范围内注册了哪些存储库。有了它,就可以使用 @InjectRepository() 装饰器将 UsersRepository 注入到 UsersService 中。
users.service.ts
import { Injectable } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm';
import { User } from './user.entity';
@Injectable()
export class UsersService {
constructor(
@InjectRepository(User)
private usersRepository: Repository<User>,
) {}
findAll(): Promise<User[]> {
return this.usersRepository.find();
}
findOne(id: number): Promise<User> {
return this.usersRepository.findOneBy({ id });
}
async remove(id: string): Promise<void> {
await this.usersRepository.delete(id);
}
}增
save(user) 创建:返回该数据的所有字段 { name: 'test', age: 18, h: 9, isActive: true }
insert(user) 创建:返回数据插入结果对象 ** 推荐
// insert返回结果
InsertResult {
identifiers: [ { h: 8 } ],
generatedMaps: [ { h: 8, isActive: true } ],
raw: ResultSetHeader {
fieldCount: 0,
affectedRows: 1,
insertId: 8,
info: '',
serverStatus: 2,
warningStatus: 0
}
}删
delete(user) 删除数据表中相应字段 ** 推荐
remove(user) 删除数据表实体
// 用法:delete({name: 'test'});
// let data = await this.userRepository.findOne({where: {name: 'test'}});
// await this.userRepository.remove(data);查
find({where: {name: 'test'}}); 查找所有符合定位数据,返回数据列表,找不到返回空列表[]
findOne({where: {name: 'test'}}); 查找第一个符合定位数据,返回当前数据,找不到返回空 null
findAndCount({where: {name: 'test'}}); 查找所有符合定位数据,返回数据列表,和总数统计
findAndCountBy({name: 'test'}) 查找所有符合定位数据,返回数据列表,和总数统计改
update({name: 'test'}, {age: 20}); 修改对应字段数据,返回修改结果对象
// 返回 UpdateResult { generatedMaps: [], raw: [], affected: 7 }其他操作方法
increment({name: 'test'}, 'age', '4'); 增加数值,成功返回改变实体
decrement({name: 'test'}, 'age', '4'); 减少数值,成功返回改变实体
count({where: {name: 'test'}}); 计数
countBy({name: 'test'}); 计数Not != LessThan < LessThanOrEqual <= MoreThan > MoreThanOrEqual >= Equal == Between Between(1,10) IsNull IsNull()
www.haizhuan.tk