簡體   English   中英

Sequelize bulkCreate 是否使用 MySQL 返回生成的 ID?

[英]Sequelize bulkCreate returns generated IDs or not with MySQL?

當我閱讀Sequelize 文檔時,它讓我認為無法從對bulkCreate的調用中返回生成的 ID。 甚至returning選項參數也說它是僅 Postgres 的功能。 這也在這個 Sequelize 問題中被引用。

但是我使用 Sequelize v5.21.3 和 MySQL 5.6.49 運行了下面的代碼,它似乎工作得很好(請注意,我什沒有傳遞returning: true選項。)

const MyEntity = sequelize.define(
  "MyEntity",
  {
    name: {
      type: DataTypes.STRING(255),
      allowNull: false
    },
  },
  {
    tableName: "my_entity"
  }
);
await MyEntity.sync();

const saved = await MyEntity.bulkCreate([
  { name: "test1" },
  { name: "test2" },
  { name: "test3" }
]);
console.log(`*** SAVED:\n ${JSON.stringify(saved, null, 2)}`);

它似乎正確返回了 id,打印了這個:

*** SAVED:
 [
  {
    "id": 1,
    "name": "test1",
    "createdAt": "2020-09-29T14:04:27.127Z",
    "updatedAt": "2020-09-29T14:04:27.127Z"
  },
  {
    "id": 2,
    "name": "test2",
    "createdAt": "2020-09-29T14:04:27.127Z",
    "updatedAt": "2020-09-29T14:04:27.127Z"
  },
  {
    "id": 3,
    "name": "test3",
    "createdAt": "2020-09-29T14:04:27.127Z",
    "updatedAt": "2020-09-29T14:04:27.127Z"
  }
]

那么真相是什么? 無論我嘗試頂部插入多少條記錄,我都可以相信返回 id 會起作用嗎? 文檔的這部分是錯誤的還是措辭不當?

成功處理程序會傳遞一個實例數組,但請注意,這些實例可能無法完全代表 DB 中行的狀態。 這是因為 MySQL 和 SQLite 不容易以可以映射到多個記錄的方式獲取自動生成的 ID 和其他默認值。 要獲取新創建的值的實例,您需要再次查詢它們。

Sequelize 代碼為 MariaDB 提供了一些解決方法,假設它們將按順序創建,不返回帶有插入的 ID,有一條評論說

//ONLY TRUE IF @auto_increment_increment is set to 1 !!

作為旁注,有趣的是不可配置且硬編碼以遞增 1 ...

./sequelize/lib/dialects/mariadb/query.js

  formatResults(data) {
    let result = this.instance;

    // update and upsert code....

    if (this.isInsertQuery(data)) {

      this.handleInsertQuery(data);

      if (!this.instance) {
        // handle bulkCreate AI primary key
        if (this.model
          && this.model.autoIncrementAttribute
          && this.model.autoIncrementAttribute === this.model.primaryKeyAttribute
          && this.model.rawAttributes[this.model.primaryKeyAttribute]
        ) {
          //ONLY TRUE IF @auto_increment_increment is set to 1 !!
          //Doesn't work with GALERA => each node will reserve increment (x for first server, x+1 for next node ...
          const startId = data[this.getInsertIdField()];
          result = new Array(data.affectedRows);
          const pkField = this.model.rawAttributes[this.model.primaryKeyAttribute].field;

// *** THIS SEQUENTIAllY INCREMENTS THE ID *** //
          for (let i = 0; i < data.affectedRows; i++) {
            result[i] = { [pkField]: startId + i };
          }
          return [result, data.affectedRows];
        }

        return [data[this.getInsertIdField()], data.affectedRows];
      }
    }

    //... more code

此代碼描述了用於獲取上述代碼所基於的表的auto_increment值的表。

./sequelize/lib/dialects/abstract/query-generator.js

  describeTableQuery(tableName, schema, schemaDelimiter) {
    const table = this.quoteTable(
      this.addSchema({
        tableName,
        _schema: schema,
        _schemaDelimiter: schemaDelimiter
      })
    );

    return `DESCRIBE ${table};`;
  }

describeTableQuery()describeTable()方法中調用: /sequelize/lib/dialects/abstract/query-abstract.js


  async describeTable(tableName, options) {
//... code
    const sql = this.queryGenerator.describeTableQuery(tableName, schema, schemaDelimiter);
    options = { ...options, type: QueryTypes.DESCRIBE };

    try {
      const data = await this.sequelize.query(sql, options);
// ...more code

MariaDB 方言類中有更多代碼可以解決不直接從數據庫返回的 ID。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM