TypeORM使用Repository方法构造带OR条件WHERE子句的JOIN查询问题
问题原因
- 核心原因是TypeORM 旧版本
find方法的语法限制:find方法的where参数不支持直接通过嵌套关联实体对象的方式过滤关联表非主键字段,当你写engines: {status: In([3,4])}这类代码时,TypeORM不会将其解析为关联表的status字段过滤,反而会将传入的对象识别为关联实体的主键匹配条件,因此生成了多余的"CarsEntity"."engineID" = @3这类外键等值条件,你编写的关联表status条件自然不会生效。 - 补充:你使用的
leftJoinAndSelect会返回关联表的所有字段,而你的原始SQL只需要主表的RowID,无需返回关联数据,换成leftJoin即可减少不必要的查询开销。
解决方案
推荐使用灵活性更高的QueryBuilder构造查询,可以100%匹配你需要的SQL逻辑:
const carRows = await this.connection .getRepository(CarsEntity) .createQueryBuilder('car') .select('car.rowID') .leftJoin('car.doors', 'doors') .leftJoin('car.wheels', 'wheels') .leftJoin('car.engines', 'engines') .where('car.status IN (:...carStatusList)', { carStatusList: [0, 2] }) .andWhere('car.retryAttempts < :retryMax', { retryMax: 5 }) .andWhere('doors.status IN (:...doorStatusList)', { doorStatusList: [3, 4] }) .andWhere('wheels.status IN (:...wheelStatusList)', { wheelStatusList: [3, 4] }) .andWhere('engines.status IN (:...engineStatusList)', { engineStatusList: [3, 4] }) .getMany();
额外说明
- 如果你使用的是TypeORM 0.3.x及以上版本,也可以通过
FindOptionsWhere的关联条件语法实现过滤,但兼容性和可调试性不如QueryBuilder,更推荐上面的写法。 - 你可以顺便检查实体类的关联注解是否正确,比如
@ManyToOne/@OneToMany的关联关系、外键字段名是否和数据库表结构对应,但当前问题的核心是查询写法错误,和实体定义关联度极低。
内容的提问来源于stack exchange,提问作者Ivelin
相关产品推荐
相关产品推荐

