NestJS typeorm 存储库的通用继承不起作用,this.function 不是函数

问题描述 投票:0回答:2

我正在尝试创建一个扩展 Repository 的自定义存储库类,以便我可以添加要从所有存储库中使用的自定义日志函数。 这是代码。

用户.service.ts:

@Injectable()
export class UserService {
    constructor(
        @InjectRepository(User)
        private readonly userRepository: BaseRepository<User>,
    ) {}

    async update(id: string, data: UpdateUserDto): Promise<UpdateResult> {
        return await this.userRepository.updateAndLog(id, data);
    }
}

BaseRepository.ts:

import { Repository, UpdateResult } from 'typeorm';


export class BaseRepository<T> extends Repository<T> {

  async updateAndLog(id: string, data: any): Promise<UpdateResult> {
    const entity = await this.findOne(id as any);
    const savedEntity = await this.update(id, data);
    // log the data here
    return savedEntity;
  }
}

所以函数的输出始终是:

[Nest] 13820  - 04/11/2023, 12:07:07 PM   ERROR [ExceptionsHandler] this.userRepository.updateAndLog is not a function

我阅读了有关自定义存储库的 typeorm 文档:https://typeorm.io/custom-repository#how-to-create-custom-repository

堆栈溢出:

github:https://github.com/typeorm/typeorm/issues/2097

但是没有任何效果,下面的代码有问题吗?

typescript oop nestjs typeorm
2个回答
1
投票

这里的问题来自

@InjectRepository(User)
:它注入了
Repository
的实例,而不是
BaseRepository
的实例。

我发现这个存储库提供了一种覆盖 TypeORM 模块提供的存储库的方法,但仅限于特定实体。

但是,我们可以调整他的方法来提供通用存储库:

@Module({
  imports: [TypeOrmModule.forFeature([User])],
  providers: [buildCustomRepositoryProvider<User>(User), UserService],
})
export class UserModule {
}

使用这样的帮助文件:

import { DataSource, Repository, UpdateResult } from 'typeorm';
import { Provider } from '@nestjs/common';
import { getDataSourceToken, getRepositoryToken } from '@nestjs/typeorm';
import { EntityClassOrSchema } from '@nestjs/typeorm/dist/interfaces/entity-class-or-schema.type';

export interface BaseRepository<T> extends Repository<T> {
  this: Repository<T>;

  updateAndLog(id: string, data: any): Promise<UpdateResult>;
}

export function buildCustomRepositoryMethods<T>(): Pick<BaseRepository<T>, 'updateAndLog'> {
  return {
    async updateAndLog(id: string, data: any): Promise<UpdateResult> {
      const entity = await this.findOne({ where: { id: id as any } });
      const savedEntity = await this.update(id, data);
      // log the data here
      return savedEntity;
    },
  };
}

export function buildCustomRepositoryProvider<T>(entity: EntityClassOrSchema): Provider {
  return {
    provide: getRepositoryToken(entity),
    inject: [getDataSourceToken()],
    useFactory: (dataSource: DataSource) => {
      // Override the default repository with a custom one
      return dataSource.getRepository(entity).extend(buildCustomRepositoryMethods<T>());
    },
  };
}

因此,

@InjectRepository(User)
将注入一个使用
Repository<User>
接口提供的方法扩展的
BaseRepository
实例。

(注意:此处使用

extend
方法创建自定义存储库,因为这是自 TypeORM 0.3 以来推荐的方法,请参阅此处


0
投票

尝试这个解决方案,我在我的应用程序中使用这个解决方案

import { Type } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { ObjectLiteral, Repository } from 'typeorm';

interface IDataService<T extends ObjectLiteral> {
  readonly repository: Repository<T>;
  findById: (id: string | number) => Promise<T | null>;
}

type Constructor<I> = new (...args: any[]) => I;

export function DataService<T extends ObjectLiteral>(
   entity: Constructor<T>,
): Type<IDataService<T>> {

   class DataServiceHost implements IDataService<T> {
     @InjectRepository(entity) public readonly repository: Repository<T>;

     public async findById(id: string | number): Promise<T | null> {
        return this.repository.findOneBy({ id } as any);
     }
   }
   return DataServiceHost;
}

从 DataService 类扩展您的服务,

class YourService extends DataService<YourDatasebaseEntity>(YourDatasebaseEntity) 
© www.soinside.com 2019 - 2024. All rights reserved.