使用TypeORM QueryBuilder的skip/take分页时出现别名找不到异常
TypeORM中
skip()/take()结合leftJoinAndMapMany报别名未找到异常的解决方案 问题场景
- 用TypeORM的QueryBuilder构建查询,通过
leftJoinAndMapMany做多表关联 - 因关联查询需求选
skip()+take()实现分页(offset()/limit()能正常跑) - 调用
skip()和take()时抛出异常:""User"" alias was not found. Maybe you forgot to join it? - 调试生成的SQL可直接在数据库执行成功,去掉关联查询后
skip()/take()恢复正常
代码示例:
const dbQuery: SelectQueryBuilder<T> = userRepository.createQueryBuilder('User'); dbQuery.leftJoinAndMapMany(...); // 此处为关联其他表的逻辑 dbQuery.skip(skip); dbQuery.take(take);
问题根因
扒TypeORM源码发现,QueryExpressionMap.prototype.findAliasByName方法接收到的aliasName参数带双引号,导致匹配不上创建查询时定义的User别名,进而抛出异常。而offset()/limit()的处理逻辑没触发这个带引号的别名查找流程,所以没报错。
可行解决方案
临时源码修复方案
修改TypeORM源码里的QueryExpressionMap.prototype.findAliasByName方法,在查找别名前先去掉参数里的引号:
QueryExpressionMap.prototype.findAliasByName = function (aliasName) { // 新增去除首尾引号的逻辑 aliasName = aliasName.replace(/^"|"$/g, ''); // 保留原有逻辑 const alias = this.aliases.find(alias => alias.name === aliasName); if (!alias) throw new AliasNotFoundError(aliasName); return alias; };
注意:
- 这是临时方案,TypeORM版本更新后会覆盖修改
- 要验证是否影响其他场景(比如本身带引号的合法别名)
无源码修改替代方案
尝试把创建查询时的别名改成小写user:
const dbQuery: SelectQueryBuilder<T> = userRepository.createQueryBuilder('user'); dbQuery.leftJoinAndMapMany(...); dbQuery.skip(skip); dbQuery.take(take);
部分场景下,大写别名可能触发TypeORM内部的引号处理逻辑,改用小写可以规避问题。
额外建议
- 如果用源码修改方案,建议用
patch-package这类工具管理修改,避免每次装依赖都要重改 - 可以去TypeORM的GitHub仓库提Issue反馈这个带引号的别名Bug,等官方修复
内容的提问来源于stack exchange,提问作者Artem
相关产品推荐
相关产品推荐

