Typeorm-SelectQueryBuilder在使用from子查询时会绑定对应实体表解决方案
一、简要介绍
Typeorm是使用node进行服务端开发时,用于与数据库打交道比较常用的orm库之一。Typeorm封装了很多API供开发者便捷的进行数据库操作。其中一个比较常用的对象就是Repository对象,它与一个实体表进行关联,因此通过这个对象,可以便捷的操作对应的实体表。
二、问题描述
现在假如存在一个Repository关联了实体表Task。现在存在一个需求需要将Form子查询的结果作为主查询的数据源。简要示例代码如下:
const builder = this.taskRepository
.createQueryBuilder()
.select('main_task.*')
.addSelect(formats)
.from((subQuery) => {
// 子查询筛选
const sub = subQuery
.select('sub_task.*')
.from(Task, 'sub_task')
.where(`sub_task.userId = ${userId}`)
.andWhere(`sub_task.planStartDate <= '${condition.end}'`)
.andWhere(`sub_task.planEndDate >= '${condition.start}'`);
return sub;
}, 'main_task')
.andWhere(`main_task.status = '${status === 1}'`)
这个查询很好懂,子查询查询出一个集合A,然后在这个集合A中筛选满足状态的数据。但筛选的结果可能会存在2份,即同一个数据会返回2条。
检查生成的SQL语句后,很容易发现问题:
SELECT main_task.*, DATE_FORMAT(main_task.planStartDate, '%Y-%m-%d') planStartDate, DATE_FORMAT(main_task.planEndDate, '%Y-%m-%d') planEndDate, DATE_FORMAT(main_task.realDate, '%Y-%m-%d') realDate FROM `task` `Task`, (SELECT sub_task.* FROM `task` `sub_task` WHERE `sub_task`.`userId` = 1 AND `sub_task`.`planStartDate` <= '2023-06-13' AND `sub_task`.`planEndDate` >= '2023-06-13') `main_task`
主查询中,Form语句后面不仅存在子查询语句,还存在Task实体表。这样被查询的2个表组成了一个联表,因此查询结果可能会返回2份。这儿不确定是不是Repository对象的设计目的之一就是要固定绑定Form实体表,即便有指定的from方法,但这显示不是我的本意。
Task实体表不是我们添加的,它在这个查询中不应该存在。通过在git上和stackoverflow去查看相关的问题,找到了相关的解决方案。
三、解决方案
一个Repository对象会和一个实体表关联,因此通过Repository对象创建SelectQueryBuilder进行Select查询操作时,会自动在Form后面添加对应实体表。因此解决方案就是可以通过EntityManager对象去创建SelectQueryBuilder对象,这样就没有与任何实体表关联。
示例代码如下:
const builder = this.taskRepository.manager // 使用manager对象创建对象
.createQueryBuilder()
.select('main_task.*')
.addSelect(formats)
.from((subQuery) => {
// 子查询筛选
const sub = subQuery
.select('sub_task.*')
.from(Task, 'sub_task')
.where(`sub_task.userId = ${userId}`)
.andWhere(`sub_task.planStartDate <= '${condition.end}'`)
.andWhere(`sub_task.planEndDate >= '${condition.start}'`);
return sub;
}, 'main_task')
.andWhere(`main_task.status = '${status === 1}'`)
转载自:https://juejin.cn/post/7244075827355992121