我正在尝试创建一个扩展 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
但是没有任何效果,下面的代码有问题吗?
这里的问题来自
@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 以来推荐的方法,请参阅此处)
尝试这个解决方案,我在我的应用程序中使用这个解决方案
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)