TypeORM自定义存储库不覆盖createQueryBuilder



我正在尝试为TypeORM实现数据库i18n。我可以从理论上做到这一点。但是我还想重写内置的存储库方法来使用i18n(基本上是拦截它们并添加查询)。如何在TypeORM存储库中覆盖createQueryBuilder?我可以覆盖findMany,findOne等方法并添加新方法。但这对createQueryBuilder不起作用。我知道我可以覆盖存储库中的所有选择方法。但我想在一个地方做,并试图覆盖createQueryBuilder。代码显示了我的自定义存储库定义。

export function TranslatableRepository<T>() {
return {
createQueryBuilder<Entity>(
alias?: string,
queryRunner?: QueryRunner
): SelectQueryBuilder<Entity> {
throw new Error();
let qb = this.manager.createQueryBuilder<Entity>(
this.metadata.target as any,
alias || this.metadata.targetName,
queryRunner || this.queryRunner
);
qb = qb.leftJoinAndSelect(
`${alias || this.metadata.targetName}.translations`,
'translation',
'translation.locale = :locale',
{
locale: this.getLocale()
}
);
return qb;
},
getLocale() {
return getLocaleFromContext();
}
} as ThisType<Repository<T> & TTranslatableRepository<T>> &
TTranslatableRepository<T>;
}

我像使用postRepository.extend(TranslatableRepository<Post>())一样使用它。上面的createQueryBuilder方法应该抛出这个错误。但它使用内置方法。这是TypeORM源代码中扩展方法的副本。

extend(custom) {
// return {
//     ...this,
//     ...custom
// };
const thisRepo = this.constructor;
const { target, manager, queryRunner } = this;
const cls = new (class extends thisRepo {})(target, manager, queryRunner);
Object.assign(cls, custom);
return cls;
}

我怎么能覆盖createQueryBuilder或有任何其他方法拦截查询?

终于找到了!我需要在实体管理器中重写createQueryBuilder方法,而不是在存储库中。

编辑:,下面的代码将覆盖entityManager,所以如果我们不想从appDataSource.manager改变默认的entityManager,我们需要提供一个新的entityManager,大概来自appDataSource.createEntityManager()

export function TranslatableRepository(manager: EntityManager) {
manager.createQueryBuilder = function createQueryBuilder<Entity>(
entityClass?: EntityTarget<Entity> | QueryRunner,
alias?: string,
queryRunner?: QueryRunner
): SelectQueryBuilder<Entity> {
let qb: SelectQueryBuilder<Entity>;
if (alias) {
qb = this.connection.createQueryBuilder(
entityClass as EntityTarget<Entity>,
alias,
queryRunner || this.queryRunner
);
} else {
qb = this.connection.createQueryBuilder(
(entityClass as QueryRunner | undefined) ||
queryRunner ||
this.queryRunner
);
}
return qb.leftJoinAndSelect(
`${alias}.translations`,
'translation',
'translation.locale = :locale',
{
locale: getLocaleFromContext()
}
);
};
return {};
}

最新更新