【问题标题】:Sequelize - avoid deleting rows of many-to-many association when inserting a new oneSequelize - 在插入新的关联时避免删除多对多关联的行
【发布时间】:2020-06-09 20:07:18
【问题描述】:

我的问题是当我执行这段代码时:

const task = await db.tasks.findByPk(1)
const user = await db.users.findByPk(4)
await user.setTasks(task)

发生这种情况:

Executing (default): SELECT `tasks`.`id`, `tasks`.`start_date` FROM `tasks` AS `tasks` WHERE `tasks`.`id` = '1';
Executing (default): SELECT `id`, `name`, `surname`, `email`, `role` FROM `users` AS `users` WHERE `users`.`id` = '4';
Executing (default): SELECT `id`, `task_id`, `user_id` FROM `users_tasks` AS `users_tasks` WHERE `users_tasks`.`user_id` = 4;
Executing (default): DELETE FROM `users_tasks` WHERE `user_id` = 4 AND `task_id` IN (2)
Executing (default): INSERT INTO `users_tasks` (`id`,`task_id`,`user_id`) VALUES (NULL,1,4);

ID 为 4 的用户之前与 ID 为 2 的任务有关联。问题是,我想保持该关联!对于我的应用程序而言,将用户分配给更多任务(反之亦然)是非常好的。

我实际上会说这是多对多关系的正常期望行为...为什么 Sequelize 在添加新行之前删除 users_tasks 上的行,我该如何防止这种情况发生?

这是我的用户模型:

module.exports = function(sequelize, DataTypes) {
    var User = sequelize.define('users', {
        id: {
            type: DataTypes.INTEGER(10).UNSIGNED,
            allowNull: false,
            primaryKey: true,
            autoIncrement: true
        },
        name: {
            type: DataTypes.STRING(50),
            allowNull: false
        },
        surname: {
            type: DataTypes.STRING(50),
            allowNull: false
        },
        email: {
            type: DataTypes.STRING(256),
            allowNull: false
        },
    }, {
        tableName: 'users',
        timestamps: false,
    })

    User.associate = function (models) {
        User.belongsToMany(models.tasks, {through: 'users_tasks', foreignKey: 'user_id'})
    }

    return User
}

这是我的任务模型:

module.exports = function(sequelize, DataTypes) {
    var Task = sequelize.define('tasks', {
        id: {
            type: DataTypes.INTEGER(10).UNSIGNED,
            allowNull: false,
            primaryKey: true,
            autoIncrement: true
        },
        start_date: {
            type: DataTypes.DATE,
            allowNull: true,
        },
    }, {
        tableName: 'tasks',
        timestamps: false
    })

    Task.associate = function (models) {
        Task.belongsToMany(models.users, {through: 'users_tasks', foreignKey: 'task_id'})
    }

    return Task
}

这是我的连接表:

module.exports = function(sequelize, DataTypes) {
    return sequelize.define('users_tasks', {
        id: {
            type: DataTypes.INTEGER(10).UNSIGNED,
            allowNull: false,
            primaryKey: true,
            autoIncrement: true
        },
        task_id: {
            type: DataTypes.INTEGER(10).UNSIGNED,
            allowNull: false,
            references: {
                model: 'tasks',
                key: 'id'
            }
        },
        user_id: {
            type: DataTypes.INTEGER(10).UNSIGNED,
            allowNull: false,
            references: {
                model: 'users',
                key: 'id'
            }
        }
    }, {
        tableName: 'users_tasks',
        timestamps: false
    })
}

我需要更改模型定义上的某些内容,还是需要更改我调用setTasks 的方式?否则,我需要做什么?为什么 Sequelize 会强制执行这种奇怪且不受欢迎的行为,即删除先前存在的关联?

【问题讨论】:

  • 默认情况下,'set' 删除任何现有的关联并添加正在传递的关联。我认为如果您想维护现有的,您可能会使用“添加”功能。这不会删除现有的关联并添加新的关联。但是请记住,如果目标表中有任何复合唯一约束并且您尝试添加重复值,db 会抛出唯一约束破坏错误。
  • @GhulamMohammedTaher 是的!这就是问题所在!我用addJams 替换了setJams,现在DELETE 不再被执行。如果您想发表您的评论作为答案,我很乐意接受它作为问题的正确答案。

标签: javascript mysql node.js orm sequelize.js


【解决方案1】:

我发现如果我想保留预先存在的关系,我应该使用add 而不是set

所以,达到我想要的结果的正确方法是这样的:

const task = await db.tasks.findByPk(1)
const user = await db.users.findByPk(4)
await user.addTasks(task)

【讨论】:

    猜你喜欢
    • 2017-10-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-11-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多