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

为什么TypeORM v0.2.40操作MySQL时未修改数据也返回affected:1

问题根因
  1. MySQL/MariaDB默认返回的affectedRows字段统计的是WHERE条件匹配到的行数,而非实际发生数据修改的行数,实际修改行数存储在返回结果的changedRows字段中。
  2. TypeORM v0.2.40版本处理MySQL/MariaDB的更新返回结果时,直接将驱动返回的affectedRows赋值给UpdateResult.affected字段,未做changedRows的映射处理,因此只要匹配到数据,无论内容是否变更,都会返回affected: 1。
  3. 原生查询会返回完整的ResultSetHeader结构,因此可以直接读取changedRows判断实际修改情况,但TypeORM封装的更新方法默认不会将该字段暴露到外层返回结果中。
可行解决方案
  • 方案1:修改数据库连接配置(适合无FOUND_ROWS()函数依赖的场景)
    在TypeORM的连接配置extra参数中添加禁用FOUND_ROWS的标志,修改后MySQL会直接将实际修改行数赋值给affectedRows,TypeORM返回的affected字段就会符合预期:

    // ormconfig 配置示例
    export default {
      type: "mysql",
      host: "127.0.0.1",
      port: 3306,
      username: "root",
      password: "your password",
      database: "your db",
      // 新增以下配置
      extra: {
        flags: "-FOUND_ROWS"
      }
    }
    

    注意:该配置会导致FOUND_ROWS()统计函数失效,如果项目中用该函数实现分页总条数统计,请选择其他方案

  • 方案2:封装自定义更新方法(适合不能修改连接配置、不想升级TypeORM的场景)
    利用TypeORM的查询构建器生成SQL,再通过原生查询执行,直接解析返回结果的changedRows字段,无需手动编写全量SQL:

    import { Repository, UpdateResult } from "typeorm";
    
    async function updateWithRealAffected<T>(
      repo: Repository<T>,
      id: number | string,
      updateData: Partial<T>,
      idKey = "id"
    ): Promise<number> {
      const qb = repo
        .createQueryBuilder()
        .update(updateData)
        .where(`${idKey} = :id`, { id });
      const [sql, params] = qb.getQueryAndParameters();
      const result = await repo.manager.query(sql, params);
      return result.changedRows;
    }
    
    // 调用示例
    const affected = await updateWithRealAffected(areaRepo, id, data, "area_id");
    
  • 方案3:升级TypeORM版本(适合可以接受版本迭代break change的场景)
    TypeORM v0.3.10及以上版本已经优化了MySQL/MariaDB的更新返回逻辑,会自动将changedRows的值映射到UpdateResult.affected字段,升级后无需额外配置即可符合预期。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.26 10:36:05