реализовать миграцию для ассоциированного метода в sequlize для удаления (уничтожения) и включения для foreignKey - PullRequest
0 голосов
/ 13 февраля 2020

Я использую базу данных MySql и у меня есть модель TypePart, у которой есть дочерняя модель с именем SubPartDetail.

Так что, как сказано в документации для продолжения, я реализовал свою модель TypePart с hasMany и SubPartDetail с belongsTo.

/models/typepart.js

'use strict';
module.exports = (sequelize, DataTypes) => {
  const TypePart = sequelize.define('TypePart', {
    name: {
      type: DataTypes.STRING(100),
      allowNull: false
    },
    section: {
      type: DataTypes.STRING(100),
      allowNull: false
    },
    nSubPart: {
      type: DataTypes.INTEGER,
      allowNull: false
    },
  }, {});
  TypePart.associate = function(models) {
    TypePart.hasMany(models.SubPartDetail, {
      foreignKey: 'typePartId',
      as: 'subpart'
    });
  };
  return TypePart;
};

/migrations/create-typepart.js

'use strict';
module.exports = {
  up: (queryInterface, Sequelize) => {
    return queryInterface.createTable('typeparts', {
      id: {
        allowNull: false,
        autoIncrement: true,
        primaryKey: true,
        type: Sequelize.INTEGER
      },
      name: {
        type: Sequelize.STRING(100),
        allowNull: false
      },
      section: {
        type: Sequelize.STRING(100),
        allowNull: false
      },
      nSubPart: {
        type: Sequelize.INTEGER,
        allowNull: false
      },
      createdAt: {
        allowNull: false,
        type: Sequelize.DATE
      },
      updatedAt: {
        allowNull: false,
        type: Sequelize.DATE
      }
    });
  },
  down: (queryInterface, Sequelize) => {
    return queryInterface.dropTable('typeparts');
  }
};

/models/subpartdetail.js

'use strict';
module.exports = (sequelize, DataTypes) => {
  const SubPartDetail = sequelize.define('SubPartDetail', {
    name: {
      type: DataTypes.STRING(50),
      allowNull: false,
    },
    typePartId: {
      type: DataTypes.INTEGER,
      allowNull: false,
      references: {
        model: 'TypeParts',
        key: 'id'
      },
    },
  }, {});
  SubPartDetail.associate = function(models) {
    SubPartDetail.belongsTo(models.TypePart, {
      foreignKey: 'typePartId',
      as: 'typepart',
      onDelete: 'CASCADE'
    });
  };
  return SubPartDetail;
};

migrations/create-subpartdetail.js

'use strict';
module.exports = {
  up: (queryInterface, Sequelize) => {
    return queryInterface.createTable('subpartdetails', {
      id: {
        allowNull: false,
        autoIncrement: true,
        primaryKey: true,
        type: Sequelize.INTEGER
      },
      name: {
        type: Sequelize.STRING(50),
        allowNull: false,
      },
      typePartId: {
        type: Sequelize.INTEGER,
        allowNull: false,
        references: {
          model: 'typeparts',
          key: 'id'
        },
      },
      createdAt: {
        allowNull: false,
        type: Sequelize.DATE
      },
      updatedAt: {
        allowNull: false,
        type: Sequelize.DATE
      }
    });
  },
  down: (queryInterface, Sequelize) => {
    return queryInterface.dropTable('subpartdetails');
  }
};

У меня есть автоматически сгенерированные модели из моего sequlize init

models/index.js

'use strict';
const fs = require('fs');
const path = require('path');
const Sequelize = require('sequelize');
const basename = path.basename(__filename);
const env = process.env.NODE_ENV || 'development';
const config = require(__dirname + '/../config/config.json')[env];
const db = {};

let sequelize;
if (config.use_env_variable) {
  sequelize = new Sequelize(process.env[config.use_env_variable], config);
} else {
  sequelize = new Sequelize(config.database, config.username, config.password, config);
}

fs
  .readdirSync(__dirname)
  .filter(file => {
    return (file.indexOf('.') !== 0) && (file !== basename) && (file.slice(-3) === '.js');
  })
  .forEach(file => {
    const model = sequelize['import'](path.join(__dirname, file));
    db[model.name] = model;
  });

Object.keys(db).forEach(modelName => {
  if (db[modelName].associate) {
    db[modelName].associate(db);
  }
});

db.sequelize = sequelize;
db.Sequelize = Sequelize;

module.exports = db;

Я выполняю миграцию с npx sequelize-cli db:migrate, и она дает мне такую ​​таблицу:

table typeparts

table typeparts

таблица subpartdetails

table subpart

В My Controller я вызываю метод запроса следующим образом:

const models = require('../models');
const typepart = express.Router();

typepart.post('/delete', (req, res) => {
    models.TypePart.findOne({
        where: { id: req.body.id }
    }).then(result => {
        if (result) {
            models.TypePart.destroy({
                where: { id: result.dataValues.id }
            }).then(r => {
                res.json({
                    message: result.dataValues,
                });
            }).catch(err => {
                // error is from here
                res.status(400).json({
                    message: { error: err },
                });
            });
        }
        else {
            res.status(400).json({
                message: { error: 'typepart does not exist' },
            });
        }
    }).catch(err => {
        res.status(400).json({
            message: { error: err },
        });
    });
});

Проблема в том, что каждый раз, когда я вызываю запрос выше, он выдает ошибку с кодом: ER_ROW_IS_REFERENCED_2

ForeignKeyConstraintError [SequelizeForeignKeyConstraintError]: Cannot delete or update a parent row: a foreign key constraint fails (`rekari`.`subpartdetails`, CONSTRAINT `subpartdetails_ibfk_1` FOREIGN KEY (`typePartId`) REFERENCES `typeparts` (`id`))
sqlMessage: 'Cannot delete or update a parent row: a foreign key constraint fails (`rekari`.`subpartdetails`, CONSTRAINT `subpartdetails_ibfk_1` FOREIGN KEY (`typePartId`) REFERENCES `typeparts` (`id`))',

Почему это произошло? Должен ли я добавить какой-то код или я ошибся при реализации метода, описанного выше?

...