【问题标题】:Sequelize ORM: Using Deferrable constraints on junction tableSequelize ORM:在联结表上使用可延迟约束
【发布时间】:2020-09-14 01:02:46
【问题描述】:

我正在尝试使用 Many:Many 与 Sequelize 的关联(针对 Postgre 数据库)。

我想创建一个 venue 并将其与单个事务中的 user 相关联。场地和用户设置为普通的Sequelize模型,并通过连接表“userVenue”分别设置为对方的“belongToMany”。

问题是我似乎无法在同一事务中创建新的 venue 及其第一个 user 关联。 Postgre 抛出以下错误:

insert or update on table "userVenues" violates foreign key constraint "userVenues_venueId_fkey"

因为新的地点还没有提交。

我认为我需要在“userVenues”联结表中将“userId”和“venueId”的外键约束设置为按照Sequelize docs 最初可延迟,但是,因为 Sequelize 正在定义联结表的“userId”和“venueId”自动,我不知道如何将它们设置为 INITIALLY_DEFERRABLE。

我尝试简单地将事务设置为 SET_DEFERRED(根据同一个文档),并且我可以在日志中看到它确实向数据库发出了命令“SET CONSTRAINTS ALL DEFERRED”,但是由于 Sequelize 似乎默认NOT (deferable) 的约束我仍然失败并出现同样的错误。如果我不使用事务,那么两个顺序 INSERTS 就可以正常工作。

有没有办法将这些外键定义为可延迟的?还是我以错误的方式处理这个问题?

非常感谢!

相关代码如下:

  // *** ASSOCIATIONS ***
  
  // The Venue association
  Venue.belongsToMany(models.user, {
    through: models.userVenue,
  });
  
    // The User association
  User.belongsToMany(models.venue, {
    through: models.userVenue,
  });
  
  
  
  // *** THE TRANSACTION ***
  const newVenue = await db.sequelize.transaction(
  { deferrable: Sequelize.Deferrable.SET_DEFERRED },
  async (t) => {
    const newRow = await db.venue.create(
      { ...payload },
      { transaction: t }
    );

    await newRow.addUser(
      socket.user,
      {
        through: { permit: 'edit' },
      },
      { transaction: t }
    );

    return newRow;
  }

【问题讨论】:

  • 你确定这个{ through: { permit: 'edit' }, }, { transaction: t }不应该是{ through: { permit: 'edit' }, transaction: t }吗?
  • 嘿,你说得对!感谢您指出了这一点。我昨天意识到了这一点,但忘了更新这篇文章。事务没有正确指定,但我没有意识到,因为当这条线失败时,整个事务回滚,所以我假设它正确地包含在事务中。但是我忘记了在托管事务中间抛出任何错误都会中止整个事情......哎呀!我不认为在这个简单的事务中我应该需要一个可延迟的约束,结果我没有......只是更好地注意语法!

标签: node.js postgresql sequelize.js


【解决方案1】:

经过进一步研究,这似乎是 Sequelize 中的一个错误:https://github.com/sequelize/sequelize/issues/8194

虽然它已被标记为错误,但尚未修复。一位乐于助人的用户在该线程中回复了我的帖子并提出了可能的修复,但目前没有拉取请求。

如果有人发现它有帮助,我目前使用的解决方法是在 DB Sync 之后运行此原始查询以更改约束。它确实需要知道约束名称。

    await sequelize.query(
      'ALTER TABLE "userVenues" ALTER CONSTRAINT "userVenues_venueId_fkey" DEFERRABLE INITIALLY DEFERRED'
    );

【讨论】:

    猜你喜欢
    • 2012-04-28
    • 2020-04-19
    • 1970-01-01
    • 2020-04-10
    • 2010-11-03
    • 2010-11-03
    • 1970-01-01
    • 2013-04-25
    • 2023-03-20
    相关资源
    最近更新 更多