如何在NestJS v8中实现自定义通用Repository(TypeORM v8.1.2)
实现NestJS v8 + TypeORM v8.1.2的通用自定义仓库
TypeORM v8.x 已经废弃了@EntityRepository装饰器,我们可以通过继承Repository并结合NestJS的依赖注入来实现通用自定义仓库,具体步骤如下:
1. 创建通用基础仓库类
先封装一个包含通用方法的基础仓库,所有实体仓库都将继承这个类,实现逻辑复用:
import { Repository, EntityManager, FindManyOptions } from 'typeorm'; export class BaseRepository<T> extends Repository<T> { constructor(entityManager: EntityManager, entity: new () => T) { super(entity, entityManager); } // 通用分页查询方法 async findPaginated(page: number = 1, limit: number = 10, options?: FindManyOptions<T>): Promise<[T[], number]> { return this.findAndCount({ skip: (page - 1) * limit, take: limit, ...options, }); } // 通用软删除方法(需实体包含deletedAt字段) async softDeleteByConditions(conditions: Partial<T>): Promise<void> { await this.update(conditions, { deletedAt: new Date() } as Partial<T>); } }
2. 为具体实体创建自定义仓库
针对每个业务实体,创建继承自BaseRepository的专属仓库,添加实体特有的自定义方法:
import { Injectable } from '@nestjs/common'; import { InjectEntityManager } from '@nestjs/typeorm'; import { EntityManager } from 'typeorm'; import { BaseRepository } from './base.repository'; import { User } from './user.entity'; @Injectable() export class UserRepository extends BaseRepository<User> { constructor(@InjectEntityManager() entityManager: EntityManager) { super(entityManager, User); } // 实体专属方法:查询活跃用户 async findActiveUsers(): Promise<User[]> { return this.createQueryBuilder('user') .where('user.isActive = :isActive', { isActive: true }) .orderBy('user.createdAt', 'DESC') .getMany(); } // 实体专属方法:根据用户名模糊查询 async findByUsernameLike(username: string): Promise<User[]> { return this.createQueryBuilder('user') .where('user.username LIKE :username', { username: `%${username}%` }) .getMany(); } }
3. 在NestJS模块中注册仓库
将自定义仓库加入模块的providers数组,确保能被依赖注入:
import { Module } from '@nestjs/common'; import { TypeOrmModule } from '@nestjs/typeorm'; import { User } from './user.entity'; import { UserRepository } from './user.repository'; import { UserService } from './user.service'; @Module({ imports: [TypeOrmModule.forFeature([User])], // 注册实体到TypeORM模块 providers: [UserRepository, UserService], exports: [UserRepository], // 如需跨模块使用,导出仓库 }) export class UserModule {}
4. 在Service中注入使用
在业务Service中直接注入自定义仓库,调用通用或专属方法:
import { Injectable } from '@nestjs/common'; import { UserRepository } from './user.repository'; import { User } from './user.entity'; @Injectable() export class UserService { constructor(private readonly userRepository: UserRepository) {} async getActiveUsers(): Promise<User[]> { return this.userRepository.findActiveUsers(); } async getUsersPage(page: number, limit: number): Promise<[User[], number]> { return this.userRepository.findPaginated(page, limit); } async searchUsersByUsername(username: string): Promise<User[]> { return this.userRepository.findByUsernameLike(username); } }
关键说明
- 通过
@InjectEntityManager获取EntityManager,传入基础仓库的构造函数,实现对实体的操作能力 - 通用仓库
BaseRepository可封装所有实体共用的逻辑,避免重复代码 - 每个实体仓库只需专注实现自身业务相关的自定义方法,保持代码职责清晰
内容的提问来源于stack exchange,提问作者soroush
相关产品推荐
相关产品推荐

