如何在其他模块中使用Typeorm通用存储库作为提供者

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

我有像这样的 Typeorm 通用存储库

import { Injectable } from '@nestjs/common'
import { IGenericRepository } from '../abstracts/generic-repository'
import {  Repository } from 'typeorm'
@Injectable()
export class GenericRepository<T> implements IGenericRepository<T> {
    private _repository: Repository<T>;

    constructor(repository: Repository<T>) {
        this._repository = repository;
    }

    getAll(): Promise<T[]> {
        return this._repository.find()
    }

    findById(id: any): Promise<T> {
        return this._repository.findOneBy(id)
    }

    create(item: T): Promise<T> {
        return this._repository.save(item)
    }

    update(id: string, item: T) {
        return this._repository
    }
}

我想使用这个存储库作为其他服务的提供者。 例如我想在用户模块中使用它

import { Module } from '@nestjs/common';
import { User } from '../entity/user.entity';
import { GenericRepositoryModule, GenericRepository } from '@app/common';
import { Repository } from 'typeorm'


@Module({
    imports: [
        GenericRepositoryModule
    ],
    providers: [ // I think something is wrong here
        {
            provide: 'userGenericRepository',
            useFactory: (genericRepository: GenericRepository<User>, user: User) => new genericRepository(Repository(user)),
            inject: [GenericRepository,User]
        }
    ],

})
export class UserModule { }

但这不起作用,有错误

我认为这个提供商

有问题

那么,我该如何解决这个问题?

dependency-injection nestjs typeorm
2个回答
4
投票

问题是您正在向他们自己的提供商提供

GenericRepository

解决这个问题的方法是:

  1. 编写一个函数来基于类创建提供者令牌;
export function createRepositoryToken(entity: any): string {
  return `${entity}__generic_repository_token`;
}
  1. 编写一个函数来创建提供者。这将帮助您节省大量代码。
export function createGenericRepositoryProvider(entity: any): Provider {
  return {
    provide: createRepositoryToken(entity),
    useFactory: (manager: EntityManager) => {
      return new GenericRepository(new Repository(entity, manager));
    },
    inject: [EntityManager],
  };
}
  1. 编写自定义装饰器
export const InjectRepo = (entity: any) =>
  Inject(createRepositoryToken(entity));
  1. 在您的模块中创建提供程序。
@Module({
  imports: [],
  providers: [
    createGenericRepositoryProvider(User);
  ]
})
export class UserModule {}

一个更简洁的选择是像这样编写模块:

// user.providers.ts
export UserRepositoryProvider = createGenericRepositoryProvider(User);

并在您的模块中使用它

@Module({
  imports: [],
  providers: [
    UserRepositoryProvider;
  ]
})
export class UserModule {}
  1. 将提供程序注入您的服务中:
@Injectable()
export class UserService {
  constructor(@InjectRepo(User) private readonly repository: GenericRepository<User>)
}

就完成了。

更新(奖励):

您还可以创建一个模块来轻松提供通用存储库。

export type GenericRepositoryModuleOptions = {
  entities: any[];
};

@Module({})
export class GenericRepositoryModule {
  static forFeature(options: GenericRepositoryModuleOptions): DynamicModule {
    const repositoryTokens = this.createRepositoryTokens(options);
    const repositoryProviders = this.createRepositoryProviders(options);
    return {
      module: GenericRepositoryModule,
      providers: repositoryProviders,
      exports: repositoryTokens,
    };
  }

  private static createRepositoryTokens(options: GenericRepositoryModuleOptions) {
    return options.entities.map(entity => createRepositoryToken(entity));
  }

  private static createRepositoryProviders(
    options: GenericRepositoryModuleOptions
  ): Provider[] {
    return options.entities.map((entity) =>
      createGenericRepositoryProvider(entity)
    );
  }
}

0
投票

它通过像这样的提供商的一些更改来解决

import { Module } from '@nestjs/common';
import { User } from '../entity/user.entity';
import { GenericRepository } from '@app/common';
import { Repository } from 'typeorm'
import { Repository, EntityManager } from 'typeorm'

@Module({
    imports: [],
    providers: [ // I think something is wrong here
        {
            provide: 'userGenericRepository',
            useFactory: (manager: EntityManager) => new genericRepository(new Repository(User, manager)),
            inject: [EntityManager]
        }
    ],

})
export class UserModule { }
© www.soinside.com 2019 - 2024. All rights reserved.