You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

NestJS 9(TypeORM 3.+)中如何扩展TypeORM Repository

NestJS 9 + TypeORM 3.x 自定义仓储实现方案

TypeORM 3.0 移除旧版@EntityRepository装饰器后,@nestjs/typeorm@9.x版本提供了适配的官方实现路径,完全可以把所有ORM相关逻辑收敛在仓储层,不需要把数据库操作堆在服务层。
首先确认依赖版本匹配:

  • typeorm版本 >= 3.0.0
  • @nestjs/typeorm版本 >= 9.0.0

方案1:封装式实现(官方推荐)

这种方式不依赖继承,通过注入原生Repository实例扩展能力,符合TypeORM 3.x的设计规范。

  1. 编写自定义仓储类
import { Injectable } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm';
import { User } from './entities/user.entity';

@Injectable()
export class UsersRepo {
  constructor(
    @InjectRepository(User)
    private readonly baseRepo: Repository<User>,
  ) {}

  // 按需绑定原生Repository方法,不需要重复实现基础逻辑
  create = this.baseRepo.create.bind(this.baseRepo);
  save = this.baseRepo.save.bind(this.baseRepo);
  find = this.baseRepo.find.bind(this.baseRepo);
  findOne = this.baseRepo.findOne.bind(this.baseRepo);
  delete = this.baseRepo.delete.bind(this.baseRepo);
  update = this.baseRepo.update.bind(this.baseRepo);

  // 自定义ORM方法:复杂查询、聚合等逻辑统一写在这里
  async getUsersCreatedAfter(time: Date) {
    return this.baseRepo
      .createQueryBuilder('user')
      .where('user.createdAt > :time', { time })
      .getMany();
  }

  async countByRole(role: string) {
    return this.baseRepo.count({ where: { role } });
  }
}
  1. 在对应业务模块中注册仓储
import { Module } from '@nestjs/common';
import { TypeOrmModule } from '@nestjs/typeorm';
import { User } from './entities/user.entity';
import { UsersRepo } from './users.repo';
import { UsersService } from './users.service';

@Module({
  imports: [TypeOrmModule.forFeature([User])],
  providers: [UsersRepo, UsersService],
  exports: [UsersRepo],
})
export class UsersModule {}
  1. 在服务层直接注入使用,和旧版本体验完全一致
import { Injectable } from '@nestjs/common';
import { UsersRepo } from './users.repo';

@Injectable()
export class UsersService {
  constructor(private readonly usersRepo: UsersRepo) {}

  async queryRecentUsers() {
    // 可直接调用原生Repository方法
    const allUsers = await this.usersRepo.find();
    // 也可调用自定义仓储方法
    const recentUsers = await this.usersRepo.getUsersCreatedAfter(new Date('2024-01-01'));
    return recentUsers;
  }
}

方案2:继承式实现(兼容旧版写法习惯)

如果更习惯旧版本继承Repository的写法,可以直接继承原生Repository类,在构造函数中初始化父类参数即可,不需要额外引入废弃装饰器。

import { Injectable } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository, DataSource } from 'typeorm';
import { User } from './entities/user.entity';

@Injectable()
export class UsersRepo extends Repository<User> {
  constructor(
    @InjectRepository(User)
    private dataSource: DataSource,
  ) {
    super(User, dataSource.createEntityManager(), dataSource.createQueryRunner());
  }

  // 直接通过this调用原生Repository方法,同时编写自定义逻辑
  async getUsersCreatedAfter(time: Date) {
    return this.createQueryBuilder('user')
      .where('user.createdAt > :time', { time })
      .getMany();
  }
}

该方案的模块注册、服务注入逻辑和方案1完全一致,不需要额外调整。

两种方案都完全遵循NestJS依赖注入规范,所有数据库操作逻辑都可以收敛到仓储层维护,不需要侵入服务层。


内容的提问来源于stack exchange,提问作者Andrii Abramov

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.26 10:09:20