【发布时间】: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