如何使用TypeORM createQueryBuilder实现指定原生SQL查询?
用TypeORM的createQueryBuilder实现你的原生SQL
嘿,我来帮你把这段原生SQL转换成TypeORM的createQueryBuilder写法,拆解开来一步步对应就很清晰啦:
首先,我们对应原生SQL的每一部分,用TypeORM的链式调用实现:
import { getRepository } from "typeorm"; import { Location } from "./entities/Location"; // 替换成你的Location实体路径 import { LocationType } from "./entities/LocationType"; // 替换成你的LocationType实体路径 import { ItemInventory } from "./entities/ItemInventory"; // 替换成你的ItemInventory实体路径 const result = await getRepository(Location) .createQueryBuilder('l') // 主表Location,别名对应原生的`l` // 1. 内连LocationType,对应原生的INNER JOIN LocationType t ON l.TypeId = t.Id // 如果你的Location实体已经和LocationType有@ManyToOne关联(比如字段叫type),可以用更简洁的写法: .innerJoin('l.type', 't') // 如果没有实体关联,就用指定条件的写法: // .innerJoin(LocationType, 't', 'l.TypeId = t.Id') // 2. 左连父级Location,对应原生的LEFT JOIN Location p ON l.ParentId = p.Id // 同理,如果Location实体有父级关联字段(比如叫parent): .leftJoin('l.parent', 'p') // 无关联时的写法: // .leftJoin(Location, 'p', 'l.ParentId = p.Id') // 3. 左连子查询的库存聚合结果,对应原生的LEFT JOIN (SELECT ...) qty ON l.Id = qty.LocationId .leftJoin( (subQuery) => { return subQuery .select('ii.locationId', 'locationId') .addSelect('SUM(ii.Units)', 'TotalUnits') .from(ItemInventory, 'ii') .groupBy('ii.locationId'); }, 'qty', 'l.Id = qty.locationId' ) // 对应原生的SELECT *,不过实际项目里建议明确指定需要的字段,避免冗余 .select('*') // 如果需要原始数据库返回的格式(而非实体实例),用getRawMany(),否则用getMany() .getRawMany();
几个需要注意的点:
- 如果你的实体之间已经通过ORM注解建立了关联关系(比如
@ManyToOne),用innerJoin('l.type', 't')这种关联字段的写法会更简洁,TypeORM会自动处理外键条件;如果没有关联,就用指定ON条件的写法。 select('*')虽然能实现和原生SQL一样的效果,但实际开发中建议明确列出需要的字段(比如.select(['l.Id', 'l.Name', 't.TypeName', 'p.Name AS ParentName', 'qty.TotalUnits'])),这样不仅性能更好,也能避免字段冲突的问题。- 如果查询结果不需要转换成实体实例,而是要原始的键值对数据,记得用
getRawMany()代替getMany()。
内容的提问来源于stack exchange,提问作者wrod7
相关产品推荐
相关产品推荐

