You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

TypeORM中已弃用findOneById的替代方案:未知主键字段名时的通用数据库查询实现

替代弃用的findOneById:无需指定主键字段的方案

我完全懂你的痛点——findOneById用起来太顺手了,弃用之后还要手动传主键字段名确实麻烦,尤其是还要兼容多主键场景。其实我们可以利用TypeORM实体的**元数据(Metadata)**来自动获取主键字段,这样就能实现和findOneById一样简洁的写法,不用手动指定主键名。

核心思路:利用Repository的元数据自动获取主键

每个实体的Repository都内置了元数据信息,其中就包含了主键字段的定义(不管是单主键还是多主键)。我们可以通过repo.metadata.primaryColumns拿到所有主键列,然后动态构建查询条件,完美替代findOneById的功能。

完整代码实现

下面是修改后的softDeleteItem函数,支持单主键和多主键场景,无需手动传主键字段名:

async function softDeleteItem(
  itemId: number | Record<string, any>, // 单主键传数值/字符串,多主键传包含所有主键键值的对象
  entityClass: ObjectType<Entity> | EntitySchema<Entity> | string,
  deletedBy: string
): Promise<boolean> {
  const repo = db.getRepository(entityClass);
  const primaryColumns = repo.metadata.primaryColumns;

  // 动态构建查询条件
  const whereCondition: Record<string, any> = {};
  if (primaryColumns.length === 1) {
    // 单主键场景:直接映射主键字段和传入的ID值
    whereCondition[primaryColumns[0].propertyName] = itemId;
  } else {
    // 多主键场景:校验传入的itemId是否包含所有主键字段
    if (typeof itemId !== 'object' || Array.isArray(itemId)) {
      throw new Error('多主键场景下,itemId必须是包含所有主键字段的对象');
    }
    primaryColumns.forEach(col => {
      const key = col.propertyName;
      if (!(key in itemId)) {
        throw new Error(`缺少必要的主键字段:${key}`);
      }
      whereCondition[key] = itemId[key];
    });
  }

  // 查询目标条目(找不到会抛出异常,和原findOneById行为一致)
  const itemToDelete = await repo.findOneByOrFail(whereCondition);
  
  // 设置删除人信息
  (itemToDelete as ISoftDeletable).deletedBy = deletedBy;
  await repo.save(itemToDelete);

  // 执行软删除
  await repo.softDelete(whereCondition);

  return true;
}

关键细节说明

  • 单主键场景:直接传入ID值(比如123),函数会自动从元数据中拿到主键字段名(比如id),构建{ id: 123 }的查询条件。
  • 多主键场景:需要传入包含所有主键键值的对象,比如{ userId: 1, orderId: 100 },函数会自动遍历所有主键字段,构建对应的查询条件。
  • 版本兼容性:如果你的TypeORM版本低于0.3.x,findOneByOrFail可能不存在,可以用findOneOrFail({ where: whereCondition })替代。
  • 异常处理:findOneByOrFail会在找不到条目时抛出异常,和原来findOneById的行为一致;如果需要兼容找不到的情况,可以换成findOne并做空值判断。

这个方案完全不需要手动指定主键字段名,写法和findOneById一样简洁,同时完美支持多主键场景,比你之前用QueryBuilder的方案更贴合原来的代码习惯。

内容的提问来源于stack exchange,提问作者Nathan Dixon

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.27 16:37:35