数据库集成(以 TypeORM 为例)
Nest 通过 @nestjs/typeorm 等包集成 ORM;生产环境用 migration,慎用 synchronize。亦可选用 Prisma、MikroORM 等(见 官方 Database)。
下文以 @nestjs/typeorm + TypeORM 为例(支持 MySQL、PostgreSQL、SQLite 等)。
一、@nestjs/typeorm 模块
安装依赖:
npm install @nestjs/typeorm typeorm mysql2 # 以 MySQL 为例
该模块导出了 TypeOrmModule,它提供了:
forRoot()/forRootAsync():配置数据库连接(应用级别配置)。forFeature():在特定模块中注册实体仓库(Repository),以便注入使用。
二、配置(TypeOrmModule.forRoot() 与 forRootAsync)
1. 同步配置(forRoot)
直接在根模块(如 AppModule)中调用,传入配置对象。
import { Module } from "@nestjs/common";
import { TypeOrmModule } from "@nestjs/typeorm";
import { User } from "./users/user.entity";
@Module({
imports: [
TypeOrmModule.forRoot({
type: "mysql",
host: "localhost",
port: 3306,
username: "root",
password: "password",
database: "test",
entities: [User], // 自动加载实体
synchronize: true, // 生产环境应设为 false,使用 migration
logging: true,
}),
],
})
export class AppModule {}
关键配置项:
type:数据库类型(mysql、postgres、sqlite等)。host、port、username、password、database:连接参数。entities:实体类列表(或使用autoLoadEntities: true自动加载)。synchronize:自动同步实体结构到数据库(仅开发/测试环境)。logging:打印 SQL 日志。
2. 异步配置(forRootAsync)
适合从环境变量或配置服务动态加载配置。支持 useFactory、useClass、useExisting。
TypeOrmModule.forRootAsync({
imports: [ConfigModule],
useFactory: (configService: ConfigService) => ({
type: "mysql",
host: configService.get("DB_HOST"),
port: +configService.get("DB_PORT"),
username: configService.get("DB_USER"),
password: configService.get("DB_PASSWORD"),
database: configService.get("DB_NAME"),
entities: [User], // 或 autoLoadEntities: true
synchronize: configService.get("NODE_ENV") !== "production",
}),
inject: [ConfigService],
});
也可以使用 useClass 指定一个自定义配置工厂类。
三、实体(Entity)
实体是映射到数据库表的一个类。使用 @Entity() 装饰器声明,字段用 @Column()、@PrimaryGeneratedColumn() 等修饰。
// user.entity.ts
import { Entity, Column, PrimaryGeneratedColumn } from "typeorm";
@Entity()
export class User {
@PrimaryGeneratedColumn()
id: number;
@Column({ length: 100 })
name: string;
@Column({ unique: true })
email: string;
@Column({ default: true })
isActive: boolean;
}
常用装饰器:
@PrimaryGeneratedColumn():自增主键。@Column():普通列,可传选项(长度、默认值、唯一等)。@CreateDateColumn()/@UpdateDateColumn():自动填充时间戳。@Index():为字段创建索引。
四、Repository 模式
Repository 是操作数据库的核心接口,提供 find、save、delete 等方法。
1. 注册 Repository
在模块中使用 TypeOrmModule.forFeature() 注册实体,这样 NestJS 的 DI 容器就会提供对应的 Repository。
// users.module.ts
import { Module } from "@nestjs/common";
import { TypeOrmModule } from "@nestjs/typeorm";
import { User } from "./user.entity";
import { UsersService } from "./users.service";
import { UsersController } from "./users.controller";
@Module({
imports: [TypeOrmModule.forFeature([User])], // 注册 User 仓库
providers: [UsersService],
controllers: [UsersController],
})
export class UsersModule {}
2. 注入 Repository
在 Service 中通过 @InjectRepository() 注入特定实体的 Repository。
// 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 | null> {
return this.usersRepository.findOneBy({ id });
}
async create(userData: Partial<User>): Promise<User> {
const newUser = this.usersRepository.create(userData);
return this.usersRepository.save(newUser);
}
async remove(id: number): Promise<void> {
await this.usersRepository.delete(id);
}
}
五、关系(Relationships)
TypeORM 支持常见的关系映射,通过装饰器声明。
| 关系 | 装饰器 | 示例 |
|---|---|---|
| 一对多 | @OneToMany + @ManyToOne | User ↔ Post |
| 一对一 | @OneToOne | User ↔ Profile |
| 多对多 | @ManyToMany + @JoinTable | User ↔ Role |
示例:User 与 Post 的一对多关系
// user.entity.ts
import { OneToMany } from "typeorm";
import { Post } from "./post.entity";
@Entity()
export class User {
@PrimaryGeneratedColumn()
id: number;
@OneToMany(() => Post, (post) => post.user)
posts: Post[];
}
// post.entity.ts
@Entity()
export class Post {
@PrimaryGeneratedColumn()
id: number;
@ManyToOne(() => User, (user) => user.posts)
user: User;
}
查询时使用 relations 选项加载关联:
const user = await this.usersRepository.findOne({
where: { id: 1 },
relations: ["posts"],
});
六、事务(Transaction)
TypeORM 提供多种事务方式,NestJS 推荐使用 QueryRunner 进行显式事务控制。
import { Injectable } from "@nestjs/common";
import { InjectDataSource } from "@nestjs/typeorm";
import { DataSource } from "typeorm";
@Injectable()
export class OrderService {
constructor(@InjectDataSource() private dataSource: DataSource) {}
async createOrderWithItems() {
const queryRunner = this.dataSource.createQueryRunner();
await queryRunner.connect();
await queryRunner.startTransaction();
try {
// 使用 queryRunner.manager 进行数据库操作
const order = await queryRunner.manager.save(Order, { userId: 1 });
const item = await queryRunner.manager.save(OrderItem, { orderId: order.id });
await queryRunner.commitTransaction();
return { order, item };
} catch (err) {
await queryRunner.rollbackTransaction();
throw err;
} finally {
await queryRunner.release();
}
}
}
注意:@Transaction 和 @TransactionManager 装饰器已过时,推荐使用 QueryRunner 方式。
七、其他 ORM / ODM
1. Sequelize (@nestjs/sequelize)
Sequelize 是另一个流行的 Node.js ORM,支持 PostgreSQL、MySQL 等。
import { SequelizeModule } from "@nestjs/sequelize";
@Module({
imports: [
SequelizeModule.forRoot({
dialect: "mysql",
host: "localhost",
port: 3306,
username: "root",
password: "password",
database: "test",
models: [User],
}),
SequelizeModule.forFeature([User]), // 注册模型
],
})
export class AppModule {}
在 Service 中注入模型:
@Injectable()
export class UsersService {
constructor(@InjectModel(User) private userModel: typeof User) {}
async findAll() {
return this.userModel.findAll();
}
}
2. Mongoose (@nestjs/mongoose)
用于 MongoDB 数据库,基于 Mongoose ODM。
import { MongooseModule } from "@nestjs/mongoose";
@Module({
imports: [
MongooseModule.forRoot("mongodb://localhost:27017/nest"),
MongooseModule.forFeature([{ name: "Cat", schema: CatSchema }]),
],
})
export class AppModule {}
Service 中使用 @InjectModel() 注入 Model。
3. Prisma(手动集成)
Prisma 是新一代 TypeScript ORM,需要手动安装 @prisma/client 并生成客户端。
// 1. 安装并初始化
npm install @prisma/client
npx prisma init
// 2. 定义 schema(prisma/schema.prisma)
model User {
id Int @id @default(autoincrement())
email String @unique
name String
}
// 3. 生成客户端
npx prisma generate
在 NestJS 中创建 Prisma 服务:
import { Injectable, OnModuleInit } from "@nestjs/common";
import { PrismaClient } from "@prisma/client";
@Injectable()
export class PrismaService extends PrismaClient implements OnModuleInit {
async onModuleInit() {
await this.$connect();
}
}
然后在其他服务中注入 PrismaService,调用其生成的方法(如 prisma.user.findMany())。
总结
| 功能 | TypeORM 方式 |
|---|---|
| 模块配置 | TypeOrmModule.forRoot / forRootAsync |
| 注册仓库 | TypeOrmModule.forFeature |
| 注入仓库 | @InjectRepository(Entity) |
| 实体定义 | @Entity()、@Column() 等 |
| 关系 | @OneToMany、@ManyToOne 等 |
| 事务 | QueryRunner 显式控制 |
| 异步配置 | useFactory + 注入配置服务 |
选择 ORM 时,关系型数据库优先 TypeORM 或 Sequelize,MongoDB 使用 Mongoose,追求类型安全和简洁可考虑 Prisma。NestJS 的数据库集成非常灵活,可根据项目需求选择合适的技术栈。
参考文献
以下链接在编写时均可正常访问:
| 资料 | 说明 |
|---|---|
| NestJS 文档 | 官方 |
| Database | 本章主题 |
| Request lifecycle | 执行顺序 |
相关文章
认证与授权
认证(Authentication):确认「你是谁」(如 JWT、Session)。 - 授权(Authorization):确认「你能做什么」(如 RBAC、策略检查)。
缓存
@nestjs/cache-manager 统一缓存 API,存储实现可插拔。
提供者与服务
Service 是最常见的 Provider,封装业务逻辑。见 module。
守卫 (Guards) 与授权
守卫决定是否放行请求,常用于认证与授权。见 auth。
配置管理(Config 模块)
@nestjs/config 加载 .env 并提供 ConfigService。见 工程化 env。
定时任务
@nestjs/schedule 基于 cron 表达式调度任务。