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

NestJS实现Repository模式时TypeORM基类方法调用报错解决

NestJS中Repository模式实现报错:Cannot read properties of undefined (reading 'create')

我在NestJS里实现标准Repository模式:定义了IUserRepository接口,让UserRepository继承TypeORM的Repository类并实现该接口,UserService通过依赖注入获取IUserRepository实例。项目编译正常,但调用控制器create方法时,UserRepository的addEntity方法里const newUser = this.create(user);抛出错误Cannot read properties of undefined (reading 'create'),试过网上方案没解决,求可行办法。


相关代码实现

仓库接口

import { CreateUserDto } from '../dto/create-user.dto';
import { UpdateUserDto } from '../dto/update-user.dto';
import { User } from '../entities/user.entity';

export interface IUserRepository {
  findAll(): Promise<User[]>;
  findById(id: number): Promise<User | undefined>;
  addEntity(user: CreateUserDto): Promise<User>;
  updateEntity(
    id: number,
    updateUserDto: UpdateUserDto,
  ): Promise<User | undefined>;
  deleteEntity(id: number): Promise<boolean>;
}

export const IUserRepository = Symbol('IUserRepository');

仓库实现类

import { Repository } from 'typeorm';
import { User } from './entities/user.entity';
import { CreateUserDto } from './dto/create-user.dto';
import { IUserRepository } from './interfaces/repository.interface';
import { UpdateUserDto } from './dto/update-user.dto';

export class UserRepository
  extends Repository<User>
  implements IUserRepository
{
  async findAll(): Promise<User[]> {
    return this.find();
  }

  async findById(id: number): Promise<User> {
    return this.findOneBy({ id: id });
  }

  async addEntity(user: CreateUserDto): Promise<User> {
    const newUser = this.create(user);
    return this.save(newUser);
  }

  async updateEntity(
    id: number,
    updateUserDto: UpdateUserDto,
  ): Promise<User | undefined> {
    const user = await this.findById(id);
    if (!user) return undefined;

    Object.assign(user, updateUserDto);
    return this.save(user);
  }

  async deleteEntity(id: number): Promise<boolean> {
    const result = await this.delete(id);
    return result.affected > 0;
  }
}

服务类

import { Inject, Injectable } from '@nestjs/common';
import { User } from './entities/user.entity';
import { CreateUserDto } from './dto/create-user.dto';
import { UpdateUserDto } from './dto/update-user.dto';
import { IUserRepository } from './interfaces/repository.interface';

@Injectable()
export class UserService {
  constructor(
    @Inject(IUserRepository) private readonly userRepository: IUserRepository,
  ) {}

  async findAllUsers(): Promise<User[]> {
    return this.userRepository.findAll();
  }

  async findUserById(id: number): Promise<User | undefined> {
    return this.userRepository.findById(id);
  }

  async createUser(createUserDto: CreateUserDto): Promise<User> {
    return this.userRepository.addEntity(createUserDto);
  }

  async updateUser(
    id: number,
    updateUserDto: UpdateUserDto,
  ): Promise<User | undefined> {
    return this.userRepository.updateEntity(id, updateUserDto);
  }

  async deleteUser(id: number): Promise<boolean> {
    return this.userRepository.deleteEntity(id);
  }
}

模块类

import { Module } from '@nestjs/common';
import { TypeOrmModule } from '@nestjs/typeorm';
import { User } from './entities/user.entity';
import { UserService } from './users.service';
import { UserController } from './users.controller';
import { UserRepository } from './users.repository';
import { IUserRepository } from './interfaces/repository.interface';

@Module({
  imports: [TypeOrmModule.forFeature([User])],
  providers: [
    UserService,
    { provide: IUserRepository, useClass: UserRepository },
  ],
  controllers: [UserController],
})
export class UsersModule {}

解决办法

这个错误的核心原因是TypeORM的Repository实例没有被正确初始化:直接用useClass注入UserRepository时,NestJS没有调用TypeORM的Repository工厂方法初始化内部核心属性(如manager、metadata),导致this指向的实例缺少TypeORM Repository的方法依赖。

方案1:标准自定义Repository注册(推荐)

修改UsersModule,把UserRepository通过TypeOrmModule.forFeature注册,让TypeORM自动完成实例初始化:

import { Module } from '@nestjs/common';
import { TypeOrmModule } from '@nestjs/typeorm';
import { User } from './entities/user.entity';
import { UserService } from './users.service';
import { UserController } from './users.controller';
import { UserRepository } from './users.repository';
import { IUserRepository } from './interfaces/repository.interface';

@Module({
  // 注册自定义Repository,让TypeORM负责初始化
  imports: [TypeOrmModule.forFeature([User, UserRepository])],
  providers: [
    UserService,
    { provide: IUserRepository, useClass: UserRepository },
  ],
  controllers: [UserController],
})
export class UsersModule {}

方案2:工厂函数手动注入依赖

如果不想通过TypeOrmModule注册自定义Repository,可通过工厂函数手动获取TypeORM初始化好的Repository实例并传递给自定义类:

import { Module } from '@nestjs/common';
import { TypeOrmModule, getRepositoryToken } from '@nestjs/typeorm';
import { User } from './entities/user.entity';
import { UserService } from './users.service';
import { UserController } from './users.controller';
import { UserRepository } from './users.repository';
import { IUserRepository } from './interfaces/repository.interface';
import { Repository } from 'typeorm';

@Module({
  imports: [TypeOrmModule.forFeature([User])],
  providers: [
    UserService,
    {
      provide: IUserRepository,
      useFactory: (userRepo: Repository<User>) => {
        const customRepo = new UserRepository();
        // 复制TypeORM Repository的核心属性到自定义实例
        Object.assign(customRepo, userRepo);
        return customRepo;
      },
      inject: [getRepositoryToken(User)],
    },
  ],
  controllers: [UserController],
})
export class UsersModule {}

方案3:构造函数注入DataSource

修改UserRepository,通过构造函数接收TypeORM的DataSource,直接获取Repository实例:

// UserRepository.ts
import { Repository, DataSource } from 'typeorm';
import { User } from './entities/user.entity';
import { CreateUserDto } from './dto/create-user.dto';
import { IUserRepository } from './interfaces/repository.interface';
import { UpdateUserDto } from './dto/update-user.dto';

export class UserRepository implements IUserRepository {
  private readonly repo: Repository<User>;

  constructor(dataSource: DataSource) {
    this.repo = dataSource.getRepository(User);
  }

  async findAll(): Promise<User[]> {
    return this.repo.find();
  }

  async findById(id: number): Promise<User> {
    return this.repo.findOneBy({ id: id });
  }

  async addEntity(user: CreateUserDto): Promise<User> {
    const newUser = this.repo.create(user);
    return this.repo.save(newUser);
  }

  async updateEntity(
    id: number,
    updateUserDto: UpdateUserDto,
  ): Promise<User | undefined> {
    const user = await this.repo.findOneBy({ id });
    if (!user) return undefined;

    Object.assign(user, updateUserDto);
    return this.repo.save(user);
  }

  async deleteEntity(id: number): Promise<boolean> {
    const result = await this.repo.delete(id);
    return result.affected > 0;
  }
}

然后在模块中配置注入:

// UsersModule.ts
import { Module } from '@nestjs/common';
import { TypeOrmModule } from '@nestjs/typeorm';
import { User } from './entities/user.entity';
import { UserService } from './users.service';
import { UserController } from './users.controller';
import { UserRepository } from './users.repository';
import { IUserRepository } from './interfaces/repository.interface';
import { DataSource } from 'typeorm';

@Module({
  imports: [TypeOrmModule.forFeature([User])],
  providers: [
    UserService,
    {
      provide: IUserRepository,
      useFactory: (dataSource: DataSource) => new UserRepository(dataSource),
      inject: [DataSource],
    },
  ],
  controllers: [UserController],
})
export class UsersModule {}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.08 08:30:06