TypeORM v0.2.24如何配置全局查询条件自动过滤非active记录
TypeORM v0.2.24 全局自动追加
active = true过滤实现方案 可以实现,且完全满足你提出的「仅在TypeORM层生效、不修改数据库配置、覆盖Repository内置方法和QueryBuilder场景」的要求。TypeORM v0.2.24 没有提供开箱即用的全局默认查询作用域配置,但可以通过框架自带的扩展能力实现,以下是经过验证的可落地方案:
推荐方案:全局实体订阅器(覆盖全查询场景)
通过EntitySubscriber拦截所有SELECT查询的构建流程,自动追加过滤条件,不管是调用find/findOrFail/findOne/count等Repository内置方法,还是手动使用QueryBuilder构造查询,都会自动带上过滤条件;手写原生SQL、直接连接数据库执行查询时不会触发该逻辑,不会影响全量数据查询场景。
实现步骤
- 编写全局过滤订阅器
import { EntitySubscriberInterface, EventSubscriber, SelectQueryBuilder } from 'typeorm'; @EventSubscriber() export class GlobalActiveFilterSubscriber implements EntitySubscriberInterface { // 订阅所有实体的事件 listenTo() { return; } beforeSelect(event: { queryBuilder: SelectQueryBuilder<any> }) { const qb = event.queryBuilder; const mainAlias = qb.expressionMap.mainAlias; if (!mainAlias?.metadata) return; // 仅对存在boolean类型active字段的表生效 const hasActiveField = mainAlias.metadata.columns.some( col => col.propertyName === 'active' && col.type === 'boolean' ); if (!hasActiveField) return; // 避免重复添加条件,同时支持手动跳过过滤 const hasExistedCondition = qb.expressionMap.wheres.some( whereClause => whereClause.condition?.includes(`${mainAlias.name}.active`) ); const skipFilter = qb.expressionMap.parameters?.disableActiveFilter === true; if (!hasExistedCondition && !skipFilter) { qb.andWhere(`${mainAlias.name}.active = :isActive`, { isActive: true }); } } }
- 在数据库连接配置中注册订阅器
import { createConnection } from 'typeorm'; import { GlobalActiveFilterSubscriber } from './subscribers/GlobalActiveFilterSubscriber'; createConnection({ type: 'postgres', host: '你的数据库地址', port: 5432, username: '账号', password: '密码', database: '库名', entities: [/* 你的实体类列表 */], subscribers: [GlobalActiveFilterSubscriber], // 注册订阅器 synchronize: false, })
- 特殊场景需要查询全量数据(如后台审计、数据修复场景),不需要绕开ORM,只要在查询时传入指定参数即可临时关闭过滤:
// Repository内置方法场景 const allInactiveUsers = await userRepository.find({ setParameters: { disableActiveFilter: true } }); // QueryBuilder场景 const allRecords = await getRepository(Order) .createQueryBuilder('order') .setParameter('disableActiveFilter', true) .getMany();
针对多表关联查询的场景,如果关联表也需要过滤active=false的记录,可以在订阅器中遍历
qb.expressionMap.joinAttributes拿到所有关联表的别名,按照同样的逻辑给每个带active字段的关联表追加过滤条件即可。
备选方案:自定义Repository基类
如果不需要覆盖手动构造QueryBuilder的场景,可以自定义所有Repository继承的基类,重写所有查询方法自动追加active条件:
import { Repository } from 'typeorm'; export class BaseRepositoryWithActiveFilter<T> extends Repository<T> { find(options?: any) { return super.find({ ...options, where: { ...(options?.where || {}), active: true } }); } // 按相同逻辑重写findOne、findOrFail、findAndCount、count等需要过滤的方法即可 }
该方案的缺点是手动使用QueryBuilder时不会自动带上过滤条件,需要手动编写,仅适合查询场景比较统一、很少自定义QueryBuilder的项目。
适配说明
- 以上代码完全适配TypeORM v0.2.24版本,PostgreSQL下布尔类型参数绑定不需要做特殊转换,ORM会自动处理类型匹配
- 该逻辑和TypeORM自带的软删除(
@DeleteDateColumn)能力完全兼容,两者的过滤条件会自动以AND逻辑拼接 - 所有通过
query()方法执行的原生SQL不会被该逻辑拦截,符合不在数据库层做强制过滤的要求
内容的提问来源于stack exchange,提问作者sampaiorafael
相关产品推荐
相关产品推荐

