Невозможно вставить строку с ненулевым внешним ключом в дальнейшем - PullRequest
0 голосов
/ 08 февраля 2020

У меня есть 3 таблицы.

Emoji, EmojiPost, User.

Полезная информация о схеме следующая:

EmojiPost.belongsTo(User, { foreignKey: 'user' });
EmojiPost.belongsTo(Emoji, {foreignKey: 'emoji_type'});
User.hasMany(EmojiPost, {foreignKey: 'user', onDelete: 'cascade'});

Когда я определил ассоциацию, подобную этой Я могу сделать следующее, чтобы вставить EmojiPost в базу данных:

var data = {
    // some fields
    user: 1,
    emoji_type: 1
}

EmojiPost.create(data);

это работает отлично. Однако я хочу, чтобы внешние ключи не обнулялись, поэтому я изменяю определение ассоциации следующим образом:

EmojiPost.belongsTo(User, { foreignKey: {field: 'user', allowNull: false} });
EmojiPost.belongsTo(Emoji, {foreignKey: {field: 'emoji_type', allowNull: false}});
User.hasMany(EmojiPost, {foreignKey: 'user', onDelete: 'cascade'});

И после этого, хотя данные содержат как emoji_type, так и пользовательские значения, я получаю не Нарушение нулевого ограничения для них обоих.

Я также попробовал следующее для вставки:

var emoji = await Emoji.findByPk(1);
var user = await User.findByPk(1);
var emoji_post = EmojiPost.build(data); // here data does not contain user and emoji_type
emoji_post.setEmoji(emoji);
emoji_post.setUser(user);
emoji_post.save();

Это приводит к ошибке, что функции setEmoji и setUser не определены. Я застрял на этом весь день, любая помощь очень ценится.

Ответы [ 2 ]

0 голосов
/ 12 февраля 2020

должно работать. Вот пример использования "sequelize": "^5.21.3":

index.ts:

import { Model, DataTypes } from 'sequelize';
import { sequelize } from '../../db';
class User extends Model {}
class EmojiPost extends Model {
  public user!: number;
  public emoji_type!: number;
}
class Emoji extends Model {}

User.init({}, { sequelize, modelName: 'User' });
EmojiPost.init({}, { sequelize, modelName: 'EmojiPost' });
Emoji.init(
  {
    emoji_id: {
      type: DataTypes.INTEGER,
      primaryKey: true,
      allowNull: false,
      autoIncrement: true,
    },
  },
  { sequelize, modelName: 'Emoji' },
);

// EmojiPost.belongsTo(User, { foreignKey: 'user' });
// EmojiPost.belongsTo(Emoji, { foreignKey: 'emoji_type' });

EmojiPost.belongsTo(User, { foreignKey: { name: 'user', allowNull: false } });
EmojiPost.belongsTo(Emoji, { foreignKey: { name: 'emoji_type', allowNull: false } });

User.hasMany(EmojiPost, { foreignKey: 'user', onDelete: 'cascade' });

(async function test() {
  try {
    await sequelize.sync({ force: true });
    await User.create();
    await Emoji.create();
    const data = { user: 1, emoji_type: 1 };
    await EmojiPost.create(data);

    const data2 = { user: null, emoji_type: null };
    await EmojiPost.create(data2);
  } catch (error) {
    console.log(error);
  } finally {
    await sequelize.close();
  }
})();

Если вы не установите опцию allowNull: false в foreignKey. Sequelize выдаст ошибку при попытке сохранить data2 из-за нарушения ограничения NOT NULL FK. Ошибка ниже ожидаемого:

name: 'SequelizeValidationError',
  errors:
   [ ValidationErrorItem {
       message: 'EmojiPost.user cannot be null',
       type: 'notNull Violation',
       path: 'user',
       value: null,
       origin: 'CORE',
       instance: [EmojiPost],
       validatorKey: 'is_null',
       validatorName: null,
       validatorArgs: [] },
     ValidationErrorItem {
       message: 'EmojiPost.emoji_type cannot be null',
       type: 'notNull Violation',
       path: 'emoji_type',
       value: null,
       origin: 'CORE',
       instance: [EmojiPost],
       validatorKey: 'is_null',
       validatorName: null,
       validatorArgs: [] } ]

Записи данных в базе данных:

node-sequelize-examples=# select * from "Emoji";
 emoji_id
----------
        1
(1 row)

node-sequelize-examples=# select * from "User";
 id
----
  1
(1 row)

node-sequelize-examples=# select * from "EmojiPost";
 id | user | emoji_type
----+------+------------
  1 |    1 |          1
(1 row)

Как видите, data2 не сохраняется в базе данных, как ожидалось.

db.ts:

const sequelize = new Sequelize({
  dialect: 'postgres',
  host: envVars.POSTGRES_HOST,
  username: envVars.POSTGRES_USER,
  password: envVars.POSTGRES_PASSWORD,
  database: envVars.POSTGRES_DB,
  port: Number.parseInt(envVars.POSTGRES_PORT, 10),
  define: {
    freezeTableName: true,
    timestamps: false,
  },
});

исходный код: https://github.com/mrdulin/node-sequelize-examples/tree/master/src/examples/stackoverflow/60127106

0 голосов
/ 12 февраля 2020

Отвечая на мой собственный вопрос. Первичный ключ Emoji - emoji_id (потому что я подчеркнул: истинно в определении). Несмотря на то, что я определил внешний ключ как emoji_type в определении, имя столбца в фактической таблице в postgres равно emoji_type, но sequelize ожидает, что я по некоторым причинам передам это значение как emojiId. Если я это сделаю, то это сработает, но я все еще не знаю, почему оно ожидает emojiId.

...