Проблема с установкой значения в столбце внешнего ключа

#foreign-keys #sequelize.js

#внешние ключи #sequelize.js

Вопрос:

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

 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:Userslrsvoweb-developmentprojectsplatoon-web-electronnode_modulessequelizelibdialectssqlitequery.js:432:16)
    at Query._handleQueryResponse (C:Userslrsvoweb-developmentprojectsplatoon-web-electronnode_modulessequelizelibdialectssqlitequery.js:77:18)
    at afterExecute (C:Userslrsvoweb-developmentprojectsplatoon-web-electronnode_modulessequelizelibdialectssqlitequery.js:260:31)
    at Statement.errBack (C:Userslrsvoweb-developmentprojectsplatoon-web-electronnode_modulessqlite3libsqlite3.js:16:21)

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

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

"ВСТАВИТЬ В `TodoModel` (`id`,`OwnerId`,`status`, `createdAt`,`updatedAt`, `MessageId`) ЗНАЧЕНИЯ (NULL,$1,$2,$3,$4,$5);"

Моя таблица TodoModel выглядит следующим образом:

СОЗДАЙТЕ ТАБЛИЦУ "TodoModel" ( 
 АВТОИНКРЕМЕНТ ПЕРВИЧНОГО КЛЮЧА с ЦЕЛЫМ числом "id", 
 Переменная "OwnerId" (255), 
 ТЕКСТ "статус" ПО УМОЛЧАНИЮ "ожидает", 
 Дата-ВРЕМЯ "createdAt" НЕ РАВНА НУЛЮ,
 Дата-ВРЕМЯ "updatedAt" НЕ равна НУЛЮ, 
 Параметр "MessageId" VARCHAR(255) НЕ равен НУЛЮ, 
 ВНЕШНИЙ КЛЮЧ ("MessageId") ССЫЛАЕТСЯ НА "MessageModel" ("uuid") ПРИ УДАЛЕНИИ, НЕТ ДЕЙСТВИЙ При КАСКАДНОМ ОБНОВЛЕНИИ 
);

Я не могу понять, почему возникает ошибка, и мне нужна помощь, потому что я фиктивный в этом ORM.

Я использую «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:

Здесь есть несколько вещей. Во-первых, если вы собираетесь использовать 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 ассоциацию как целое число. Чтобы изменить его на string, вы должны определить поле в модели, а в ассоциации использовать его в качестве внешнего ключа.

 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
});