TypeORM连接表软删除关联:如何排除已软删链接的关联实体?
解决TypeORM多对多关联中过滤软删除连接表记录的问题
软删除关联链接并不是糟糕的设计,它适合需要保留关联历史、支持恢复操作或审计的场景。下面是两种可行的解决方法:
方法一:在QueryBuilder中显式过滤连接表的软删除记录
直接在查询中关联连接表,并添加DeletedAt IS NULL的过滤条件,确保只返回未被软删除的关联:
const users = await myRepository.createQueryBuilder('User') .innerJoinAndSelect('User.Groups', 'Groups') // 显式连接连接表并过滤软删除记录 .innerJoin('JuctionTable', 'junction', `junction.UserId = User.Id AND junction.GroupId = Groups.Id AND junction.DeletedAt IS NULL`) .getMany();
或者简化写法,在关联Groups时直接附加过滤条件:
const users = await myRepository.createQueryBuilder('User') .innerJoinAndSelect( 'User.Groups', 'Groups', '(SELECT junction.DeletedAt FROM JuctionTable junction WHERE junction.UserId = User.Id AND junction.GroupId = Groups.Id) IS NULL' ) .getMany();
方法二:改用OneToMany + ManyToOne映射连接表
将原有的多对多拆分为两个一对多关联,直接映射连接表实体,这样能更灵活地控制软删除逻辑:
调整实体定义
@Entity('JuctionTable') export class Juction { @PrimaryColumn() UserId: number; @PrimaryColumn() GroupId: number; @DeleteDateColumn() DeletedAt: Date; @ManyToOne(() => UserEntity, user => user.junctions) @JoinColumn({ name: 'UserId' }) user: UserEntity; @ManyToOne(() => GroupEntity, group => group.junctions) @JoinColumn({ name: 'GroupId' }) group: GroupEntity; } @Entity('UsersTable') export class UserEntity { @PrimaryColumn() Id: number; @Column() Name: string; @OneToMany(() => Juction, junction => junction.user) junctions: Juction[]; } @Entity('GroupsTable') export class GroupEntity { @PrimaryColumn() Id: number; @Column() Name: string; @OneToMany(() => Juction, junction => junction.group) junctions: Juction[]; }
编写查询语句
通过连接过滤后的连接表,再关联对应的组:
const users = await myRepository.createQueryBuilder('User') .leftJoinAndSelect('User.junctions', 'junction', 'junction.DeletedAt IS NULL') .leftJoinAndSelect('junction.group', 'Groups') .getMany();
这种方式的优势是能直接对连接表的软删除进行更精细化的控制,比如在实体关联时添加默认过滤(可以结合@Where装饰器),避免每次查询都重复写条件。
内容的提问来源于stack exchange,提问作者Jonas
相关产品推荐
相关产品推荐

