Проблема с установкой значения в столбце внешнего ключа - PullRequest
1 голос
/ 27 марта 2019

Я использую Sequelize.js с базой данных SQLite и столкнулся с вопросом об установке значения для внешнего ключа. У меня есть следующий код:

const MessageModel = sequelize.define('MessageModel ', {
    uuid: DataTypes.STRING,
    authorId: DataTypes.STRING,
    // ... other props
  }, {});

const TodoModel = sequelize.define('TodoModel', {
    ownerId: DataTypes.STRING,
    status: {
      type: DataTypes.STRING,
      defaultValue: 'pending'
    }
  }, {});

TodoModel.belongsTo(MessageModel , {
    foreignKey: {
        name: 'messageId',
        field: 'messageId',
        allowNull: false
    },
    targetKey: 'uuid'
});

MessageModel.create({
   uuid: 'testUUIDForExample'
   // other props
}).then(message => {

   console.log(`Message's created successful`);

   TodoModel.create({
      ownerId: 'id-string',
      status: 'test-status',
      messageId: 'testUUIDForExample'
   })
})

Sequelize создает строку MessageModel в БД, но она падает, когда пытается создать TodoModel с этой ошибкой:

DatabaseError: SQLITE_ERROR: foreign key mismatch - "TodoModel" referencing "MessageModel "
    at Query.formatError (C:\Users\lrsvo\web-development\projects\platoon-web-electron\node_modules\sequelize\lib\dialects\sqlite\query.js:432:16)
    at Query._handleQueryResponse (C:\Users\lrsvo\web-development\projects\platoon-web-electron\node_modules\sequelize\lib\dialects\sqlite\query.js:77:18)
    at afterExecute (C:\Users\lrsvo\web-development\projects\platoon-web-electron\node_modules\sequelize\lib\dialects\sqlite\query.js:260:31)
    at Statement.errBack (C:\Users\lrsvo\web-development\projects\platoon-web-electron\node_modules\sqlite3\lib\sqlite3.js:16:21)

Err.original.message: "SQLITE_ERROR: foreign key mismatch - "TodoModel" referencing "MessageModel"

Сгенерированный SQL:

"INSERT INTO `TodoModel` (`id`,`ownerId`,`status`,`createdAt`,`updatedAt`,`messageId`) VALUES (NULL,$1,$2,$3,$4,$5);"

Моя таблица TodoModel выглядит так:

CREATE TABLE "TodoModel" (
    "id"            INTEGER PRIMARY KEY AUTOINCREMENT,
    "ownerId"   VARCHAR(255),
    "status"    TEXT DEFAULT 'pending',
    "createdAt" DATETIME NOT NULL,
    "updatedAt" DATETIME NOT NULL,
    "messageId" VARCHAR(255) NOT NULL,
    FOREIGN KEY("messageId") REFERENCES "MessageModel"("uuid") ON DELETE NO ACTION ON UPDATE CASCADE
);

Я не могу понять, почему произошла ошибка, и мне нужна помощь, потому что я глупец в этом ОРМ.

Я использую "sequelize": "^ 5.1.0" с SQLite.

Файл MyConfig:

const Sequelize = require("sequelize");
const electron = require('electron');
const storagePath = electron.app.getPath('userData') + '/plt.db';

module.exports = {
  development: {
    dialect: "sqlite",
    storage: storagePath,
    username: null,
    password: null,
    operatorsAliases: Sequelize.Op,
    define: { freezeTableName: true },
    query: { raw: true }, // Always get raw result
    logging: true,
  },
};

1 Ответ

1 голос
/ 27 марта 2019

Здесь есть пара вещей.Во-первых, если вы собираетесь использовать uuid в MessageModel в качестве первичного ключа, вы должны определить его, в противном случае у вас будет поле id по умолчанию.

const MessageModel = sequelize.define('MessageModel ', {
  uuid:{ // if this is your primary key you have to define it
    type: DataTypes.STRING,  //there is also DataTypes.UUID
    allowNull: false,
    primaryKey: true,
    unique: true
  }, 
  authorId: DataTypes.STRING,
  // ... other props
}, {});

Затем в TodoModel выустановка ассоциации messageId как целого числа.Чтобы изменить его на строку, вы должны определить поле в модели, а в ассоциации использовать его в качестве внешнего ключа.

const TodoModel = sequelize.define('TodoModel', {
  ownerId: DataTypes.STRING,
  status: {
    type: DataTypes.STRING,
    defaultValue: 'pending'
  },
  messageId: { //you also have to add the field on your model and set it as STRING, because on the association Sequelize by default is going to use INTEGER
    type: DataTypes.STRING,
    allowNull: false
  }
}, {});

TodoModel.belongsTo(MessageModel , {
  as: 'Message',
  foreignKey: 'messageId', // and you only set the foreignKey - Same name as your field above
});
...