【问题标题】:Sequelize.js onDelete: 'cascade' is not deleting records sequelizeSequelize.js onDelete:“级联”不删除记录续集
【发布时间】:2014-06-01 11:16:09
【问题描述】:

我有Product 表和以下列[id, name, CategoryId]Category 表和[id, name]

产品型号:-

module.exports = function(sequelize, DataTypes) {
  var Product = sequelize.define('Product', {
    name: DataTypes.STRING
  }, {
    associate: function(models) {
      Product.belongsTo(models.Category);
    }
  });
  return Product
}

类别模型:-

module.exports = function(sequelize, DataTypes) {
  var Category = sequelize.define('Category', {
    name: { type: DataTypes.STRING, allowNull: false }
  }, {
    associate: function(models) {
      Category.hasMany(models.Product, { onDelete: 'cascade' });
    }
  });
  return Category
}

当我删除类别时,它只删除类别而不是与之关联的相应产品。我不知道为什么会这样?

更新: 续集版sequelize 1.7.0

================================================ ================================== 回答(我是如何解决的。):-

我通过使用Alter 命令在数据库上添加约束来实现这一点,因为Add Foreign Key Constraintmigrationsequelize 中的一个开放bug

ALTER TABLE "Products"
ADD CONSTRAINT "Products_CategoryId_fkey" FOREIGN KEY ("CategoryId")
REFERENCES "Categories" (id) MATCH SIMPLE
ON DELETE CASCADE

【问题讨论】:

  • sequelize.sync 的输出是什么?是否添加具有删除约束的外键?你是哪个版本的?
  • @JanAagaardMeier 产品表具有 CategoryId 列,但未添加外键约束。如何添加带有删除约束的外键?
  • 添加外键约束是否需要添加迁移?
  • @Sampat,您编辑此问题的方式令人困惑。如果 agchou 的答案有效,您应该接受它作为答案,而不是修改您的问题以使其看起来从未在代码中出现错误。它会让其他人更清楚地看到包含问题的问题,以及解决问题的公认答案。

标签: node.js sequelize.js


【解决方案1】:

我相信您应该将 onDelete 放在 Category 模型而不是 products 模型中。

module.exports = function(sequelize, DataTypes) {
  var Category = sequelize.define('Category', {
    name: { type: DataTypes.STRING, allowNull: false }
  }, {
    associate: function(models) {
      Category.hasMany(models.Product, { onDelete: 'cascade' });
    }
  });
  return Category
}

【讨论】:

  • 这对我不起作用,直到我也添加了hooks: true。不确定这是错误还是设计
【解决方案2】:

从 "sequelize": "^3.5.1" 开始,它仅在您将 onDelete='CASCADE' 放入 belongsTo 声明时才有效,这就是您的情况下的 Product 模型。这与文档相矛盾:http://sequelize.readthedocs.org/en/latest/api/associations/index.html?highlight=onDelete#hasmanytarget-options

请看这个问题:Sequelize onDelete not working

【讨论】:

  • 使用 hasMany() 对我来说效果很好,但我必须在选项中添加“hooks: true”。像 User.hasOne(Profile, {onDelete: 'cascade', hooks:true})
  • 喜欢@SoichiHayashi,{onDelete: 'cascade', hooks: true} hasMany 协会为我工作。我在续集“3.30”。以相反的方式进行关联实际上给我带来了一些问题。
【解决方案3】:

由于偏执,我终于发现它对我不起作用。 Sequelize 不处理cascade,而是执行 MySQL 级联删除。话虽如此,如果您对表格使用偏执狂 - 级联将不会发生,因为记录并没有真正从表格中删除。

【讨论】:

  • 我非常想念 Hibernate
  • 续集是可憎的。
【解决方案4】:

我正在使用 Sequelize 4.38.0。

我必须将onDelete: 'CASCADE' 不仅放在关联定义上,还要放在迁移文件中。

// in models/user.js
User.associate = models => {
  User.belongsTo(models.Organization, {
    foreignKey: { name: 'organizationId', allowNull: true },
    onDelete: 'CASCADE',
  })
}

// in migrations/create-users.js
up: (queryInterface, Sequelize) => {
  return queryInterface.createTable('Users', {
    // other fields...
    organizationId: {
      type: Sequelize.INTEGER,
      allowNull: true,
      onDelete: 'CASCADE',
      references: {
        model: 'Organizations',
        key: 'id',
        as: 'organizationId',
      },
    },
  })
},

【讨论】:

  • 我曾经运行过迁移文件,现在我在其中添加了onDelete: 'CASCADE',。那么重新运行它会将这个东西添加到我的数据库中的表中而不会弄乱任何其他东西吗?
【解决方案5】:

这里的问题是生成的一些时间迁移脚本缺少CONSTRAINT for foreign key

我仍然收到问题事件,请关注 official document for { onDelete: 'cascade', hooks: true }

这是我的解决方案:

第 1 步:像往常一样创建迁移文件,但还没有 foreign key。记得像你一样定义associate

    Product.belongsTo(models.Category);

    Category.hasMany(models.Product);

第 2 步:创建迁移脚本以将 foreign key 列添加到表中:

'use strict';
module.exports = {
  up: (queryInterface, Sequelize) => {
    return queryInterface.addColumn(
      'Product', // name of Source model
      'categoryId', // name of the key we're adding 
      {
        type: Sequelize.INTEGER,
        references: {
          model: 'Category', // name of Target model
          key: 'id', // key in Target model that we're referencing
        },
        onUpdate: 'CASCADE',
        onDelete: 'CASCADE',
      }
    );
  },
  down: (queryInterface, Sequelize) => {
    return queryInterface.removeColumn(
      'Product', // name of Source model
      'categoryId' // key we want to remove
    );
  }
};

希望对您有所帮助!

我通过组合找到了这个解决方案:

【讨论】:

  • 它有效!谢谢!
  • 为我工作,但必须输入复数名称。 references: {model: 'Questions'} 为我工作,但 references: {model: 'Question'} 没有。
【解决方案6】:

hasMany 关联上添加 onDelete 级联并将钩子设置为 true 像这样

 Category.hasMany(models.Product, { onDelete: 'cascade', hooks:true });

【讨论】:

【解决方案7】:

OP在问题中添加的答案:

我通过使用Alter 对数据库添加约束来实现这一点 命令,因为 Add Foreign Key Constraintmigration 是 在sequelize 中打开 [bug][1]。

ALTER TABLE "Products"
ADD CONSTRAINT "Products_CategoryId_fkey" FOREIGN KEY ("CategoryId")
REFERENCES "Categories" (id) MATCH SIMPLE
ON DELETE CASCADE

【讨论】:

    【解决方案8】:

    我不知道为什么,但是这个{onDelete: 'cascade', hooks: true} 对我不起作用。 如果您遇到同样的问题,请尝试在模型的 migration 文件中添加 reference 相关代码。

    "use strict";
    module.exports = {
        up: async (queryInterface, Sequelize) => {
            await queryInterface.createTable("TravelDetails", {
                id: {
                    ......
                },
                event_id: {
                    type: Sequelize.INTEGER,
                    onDelete: "CASCADE",
                    references: {
                        model: "Events",
                        key: "id",
                        as: "eventData",
                    },
                },
            });
        },
        down: async (queryInterface, Sequelize) => {
            await queryInterface.dropTable("TravelDetails");
        },
    };
    

    【讨论】:

      【解决方案9】:

      我无法管理最新的 "sequelize": "^6.6.5" 关联级联以使用此处提到的任何提示在现有的 postgres 数据库上工作,因此必须将其替换为模型 beforeDestroy 钩子,如下所示

      User.beforeDestroy(async user => {
        await Role.destroy({ where: { userId: user.id } })
      })
      

      【讨论】:

        【解决方案10】:

        您确定要声明模型之间的关联吗?

        /models/index.js

        const Category  = require('./Category');
        const Product = require('./Product');
        const ProductTag = require('./ProductTag');
        const Tag = require('./Tag');
        
        Category.associate({Product});
        Product.associate({Category,Tag});
        Tag.associate({Product});
        
        module.exports={Category,Product,ProductTag,Tag};
        

        模型 Category.js

        'use strict';
        const {Model, DataTypes} = require('sequelize');
        const sequelize = require('../config/connection.js');
        
        class Category extends Model {
            /**
             * Helper method for defining associations.
             * This method is not a part of Sequelize lifecycle.
             * The `models/index` file will call this method automatically.
             */
            static associate({Product}) {
                // define association here
                console.log('Category associated with: Product');
                this.hasMany(Product, {
                    foreignKey: 'category_id',
                    onDelete: 'CASCADE'
                });
            }
        }
        
        Category.init({
            category_id: {type: DataTypes.INTEGER, autoIncrement: true, allowNull: false, primaryKey: true},
            category_name: {type: DataTypes.STRING, allowNull: false}
        }, {
            sequelize,
            timestamps: false,
            freezeTableName: true,
            underscored: true,
            modelName: "Category",
        });
        
        module.exports = Category;
        
        

        【讨论】:

          【解决方案11】:

          至于sequelize ^6.6.5,因为这个话题在搜索sequelize CASCADE时很热门:

          我必须在 hasMany 和 belongsTo 关联上都使用 onDelete:'cascade' 才能使其工作。

           Product.belongsTo(models.Category, { onDelete: 'CASCADE' });
           Category.hasMany(models.Product, { onDelete: 'CASCADE' });
          

          【讨论】:

            【解决方案12】:

            您只需更新您的产品迁移文件。 为了在删除要与子产品一起删除的类别时,您需要在产品迁移中具有以下内容

            ...
            categoryId: {
                type: Sequelize.INTEGER,
                references : {
                  model : 'Category',
                  key : 'id'
                },
                onUpdate: 'CASCADE',
                onDelete: 'CASCADE',
            },
            ...
            

            不需要在模型中添加这个 { onDelete: '级联' }

            【讨论】:

              【解决方案13】:

              删除父记录,同时删除子记录。

              添加到子文件

              onDelete: 'cascade'
              

              它成功了。

              例如

              /migrations/profile.js(外键是'user_id')

              'use strict'
              module.exports = {
                up: async (queryInterface, Sequelize) => {
                  await queryInterface.createTable('profiles', {
                    id: {
                      allowNull: false,
                      primaryKey: true,
                      type: Sequelize.UUID,
                      defaultValue: Sequelize.UUIDV4,
                    },
                    name: {
                      allowNull: false,
                      type: Sequelize.STRING,
                    },
                    age: {
                      allowNull: false,
                      type: Sequelize.STRING,
                    },
                    user_id: {
                      allowNull: false,
                      type: Sequelize.UUID,
                      references: { model: 'users', key: 'id' },
                      onDelete: 'CASCADE',    ← ※ Add here. ※
                    },
                  })
                },
                down: async (queryInterface, Sequelize) => {
                  await queryInterface.dropTable('profiles')
                },
              }
              
              

              【讨论】:

                猜你喜欢
                • 1970-01-01
                • 1970-01-01
                • 2015-02-12
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 2011-08-18
                相关资源
                最近更新 更多