NestJS+TypeORM如何默认排除关联子表已软删除的父行?
解决方案:NestJS + TypeORM 软删除关联过滤
核心原因
你之前用child: Not(IsNull())无效,是因为软删除的子实体并未从数据库中删除,只是deletedAt字段被赋值,父表关联的child字段并非null,只是该子实体的deletedAt有值,所以这个判断逻辑不生效。
内置实现方案
1. 直接在查询条件中过滤子表软删除状态
在查询父表时,直接通过关联字段的deletedAt条件过滤,只匹配未被软删除的子实体:
// 查询所有关联未软删除子实体的父表数据 const parents = await this.parentRepository.find({ where: { child: { deletedAt: IsNull() } }, relations: ['child'] // 按需关联子表 });
如果是一对多关联(父表对应多个子表行),要排除所有子行都被软删除的父表数据,可使用QueryBuilder的HAVING子句:
const parents = await this.parentRepository.createQueryBuilder('parent') .leftJoin('parent.children', 'child') .groupBy('parent.id') .having('COUNT(child.id) > 0 AND SUM(CASE WHEN child.deletedAt IS NOT NULL THEN 1 ELSE 0 END) = 0') .getMany();
2. 定义关联时设置默认过滤条件
在父实体的关联字段上,直接添加默认的软删除过滤规则,每次加载关联数据时自动排除已软删除的子实体:
// Parent.entity.ts @Entity() export class Parent { // ... 其他字段 // 一对一关联示例 @OneToOne(() => Child, { eager: true, // 按需开启自动加载 where: { deletedAt: IsNull() } // 关联时默认过滤软删除子实体 }) child: Child; // 一对多关联示例 @OneToMany(() => Child, child => child.parent, { where: { deletedAt: IsNull() } }) children: Child[]; }
这样查询父表时,关联的子实体只会包含未被软删除的行;若父表对应的子实体全被软删除,该父行因关联条件不匹配不会被查询出来。
3. 全局默认过滤:使用实体订阅者
如果需要所有父表查询都自动应用该过滤规则,无需手动写条件,可通过Entity Subscriber实现全局拦截:
// parent.subscriber.ts import { EntitySubscriberInterface, EventSubscriber, BeforeFind } from 'typeorm'; import { Parent } from './parent.entity'; @EventSubscriber() export class ParentSubscriber implements EntitySubscriberInterface<Parent> { listenTo() { return Parent; } @BeforeFind() beforeFind(queryBuilder) { // 自动添加子表软删除过滤条件,一对多关联需调整为 leftJoin('parent.children', 'child') queryBuilder.leftJoin('parent.child', 'child').andWhere('child.deletedAt IS NULL'); } }
然后在Module中注册该订阅者:
@Module({ imports: [ TypeOrmModule.forFeature([Parent, Child]), TypeOrmModule.forRoot({ // ... 数据库配置 subscribers: [ParentSubscriber] // 注册订阅者 }) ] }) export class AppModule {}
注意事项
- 确保子实体已正确添加软删除字段:
// Child.entity.ts @DeleteDateColumn() deletedAt: Date; - 使用QueryBuilder时,注意关联表的别名要和条件中的别名保持一致。
内容的提问来源于stack exchange,提问作者MarioZ
相关产品推荐
相关产品推荐

