【问题标题】:Sequelize create transaction with include and junction tableSequelize 使用包含和联结表创建事务
【发布时间】:2018-03-02 19:26:09
【问题描述】:

我正在尝试插入一条通过联结表与其他 2 个实体关联的新记录。像这样:

人员 -- 部署 -- 设备

人员和部署表:

module.exports = function(sequelize, Sequelize) {

  var Staff = sequelize.define('staff', {

    _id: {
      autoIncrement: true,
      primaryKey: true,
      type: Sequelize.INTEGER
    },

    _firstname: {
      type: Sequelize.STRING,
      notEmpty: true
    },

    _lastname: {
      type: Sequelize.STRING
    },

    _phonework: {
      type: Sequelize.STRING
    },

    _phonehome: {
      type: Sequelize.STRING
    },

    _img: {
      type: Sequelize.STRING
    },

    _emailpersonal: {
      type: Sequelize.STRING
    },

    _emailwork: {
      type: Sequelize.STRING
    },

    _position: {
      type: Sequelize.STRING
    },

    _notes: {
      type: Sequelize.STRING
    },

    _status: {
      type: Sequelize.STRING,
      defaultValue: 'active'
    }

  });

  return Staff;

};


module.exports = function(sequelize, Sequelize) {

  var Deployment = sequelize.define('deployment', {

    _id: {
      autoIncrement: true,
      primaryKey: true,
      type: Sequelize.INTEGER
    },

    _datedeployed: {
      type: Sequelize.DATEONLY,
      notEmpty: true
    },

    _datereturned: {
      type: Sequelize.DATEONLY
    },

    _city: {
      type: Sequelize.STRING
    },

    _province: {
      type: Sequelize.STRING
    },

    _country: {
      type: Sequelize.STRING
    },


    _unitnumber: {
      type: Sequelize.STRING
    },

    _comments: {
      type: Sequelize.TEXT
    },

    _productid: {
      type: Sequelize.INTEGER
    },

    _contractid: {
      type: Sequelize.INTEGER
    },

    _deploymenttypeid: {
      type: Sequelize.INTEGER
    },

    _finalsold: {
      type: Sequelize.NUMERIC(17,3)
    },

    _pricing: {
      type: Sequelize.TEXT,
      get: function () {
        return JSON.parse(this.getDataValue('value'));
      },
      set: function (value) {
        this.setDataValue('value', JSON.stringify(value));
      }
    },

    _status: {
      type: Sequelize.STRING,
      defaultValue: 'active'
    },

    createdBy: {
      type: Sequelize.STRING
    }

  });


  return Deployment;

};

我的联结表代码是这样的:

  module.exports = function(sequelize, Sequelize) {

  var DeploymentEquipment = sequelize.define('deploymentEquipment', {

  });

  DeploymentEquipment.associate = function(models){
    models.equipment.belongsToMany(models.deployment, {through: models.deploymentEquipment, foreignKey: 'equipmentId'});
    models.deployment.belongsToMany(models.equipment, {through: models.deploymentEquipment, foreignKey: 'deploymentId'});
  };


  return DeploymentEquipment;

};


module.exports = function(sequelize, Sequelize) {

  var DeploymentCrew = sequelize.define('deploymentCrew', {

    _timex: {
      type: Sequelize.DATEONLY,
      notEmpty: true
    },

    _dateon: {
      type: Sequelize.DATEONLY
    },

    _dateoff: {
      type: Sequelize.DATEONLY
    },

    _role: {
      type: Sequelize.STRING
    }

  });

  DeploymentCrew.associate = function(models){
    models.staff.belongsToMany(models.deployment, {through: models.deploymentCrew, foreignKey: 'staffId'});
    models.deployment.belongsToMany(models.staff, {through: models.deploymentCrew, foreignKey: 'deploymentId'});
  };


  return DeploymentCrew;

};

这一切似乎都很好。但是我的 create 语句在 insert 语句中省略了 deploymentid。这是我的代码:

  var deployment = req.body;
  var crew = req.body._deploymentcrew;
  var equipment = req.body._deploymentequipment;

    //insert new deployment - start transaction, add deployment, get ID, loop through crew, loop through equipment
    models.sequelize.transaction(t =>{
      var promises = [];
      return models.deployment.create(req.body, {transaction: t}).then(function(newDeployment) {
        for(var i=0; i < equipment.length; i++){
          var equip = equipment[i];
          equip.deploymentid = newDeployment.id;
          equip.equipmentId = equipment[i].id;
          var newPromise = models.deploymentEquipment.create(equip, promises.push(newPromise));
        }

        for(var i=0; i < crew.length; i++){
          var staff = crew[i];
          staff.deploymentid = newDeployment.id;
          staff.staffId = crew[i].staff.id;
          var newPromise = models.deploymentCrew.create(staff, promises.push(newPromise));
        }

        return Promise.all(promises)
      });

当我查看控制台时,这是插入语句:

执行(默认):INSERT INTO deploymentCrews (_timex,_dateon,_dateoff ,_role,createdAt,updatedAt,staffId) VALUES ('2018-03-01 ','2018-03-12',N ULL,'铅','2018-03-02 19:21:10','2018-03-02 19:21:10',5);

注意有staffId,但没有deploymentId。有什么想法为什么? 我曾尝试使用 include:[models._deploymentcrew],但不确定用这种方式处理事务。

任何建议将不胜感激。谢谢!

【问题讨论】:

  • 您可以添加人员和部署表定义吗? @enfrost
  • 我已经更新了答案。让我知道这个作品@enfrost
  • 嗯,我试过了,同样的问题。我也试过 return models.deployment.create(deployment, {include: [models.deploymentCrew, models.deploymentEquipment]});并得到错误deploymentCrew is not associated to deploy!我还确保从数据库中删除所有外键,删除表并重新同步。好奇怪,我会继续玩的
  • 是的,继续尝试☺️ 发布答案,当你解决它时。有趣

标签: node.js many-to-many sequelize.js


【解决方案1】:

在创建 N:M 关联时,我们需要指定两个表的外键,如下所示

Staff.associate = function(models){
    Staff.belongsToMany(models.deployment, {through: models.deploymentCrew, foreignKey: 'staffId'});
};

Deployment.associate = function(models) {
   Deployment.belongsToMany(models.staff, {through: models.deploymentCrew, foreignKey: 'deploymentId'});
};

将以上内容添加到相应的表定义中并删除 deploymentCrew 中的关联

【讨论】:

  • 我没有指定这些,但是当我查看随后从我的原始语句创建的表时,外键已经定义了。这是正常行为吗?
  • 是的。因为那些是主键。如果这个答案消除了你的疑问。请将答案标记为已验证,以便对其他人有所帮助。 @enfrost
  • 我根据您的示例为两个联结表指定了两个外键。删除表,同步和查询 sequelize 生成仍然遗漏 deploymentId
  • 它应该可以工作,确保你没有任何错别字错误@enfrost
  • 嗯,我检查了三次,没有错别字。也许我必须使用 include 参数?
猜你喜欢
  • 1970-01-01
  • 2016-04-01
  • 1970-01-01
  • 2014-11-10
  • 2022-12-23
  • 2018-07-13
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多