gpt4 book ai didi

javascript - 插入事务后如何保存一对多关系

转载 作者:太空宇宙 更新时间:2023-11-04 15:41:38 25 4
gpt4 key购买 nike

我在 Node v6.9.5 上的 Express v4.15.2 服务器中使用 Bookshelf v0.10.3 和 Knex v0.12.9。

我有一个 user 表,其中包含关联的 identity 表,并由 identity_user 表连接。这些表是使用 Knex 创建的:

Promise.all([
knex.schema.createTable('user', table => {
table.increments('id');
table.string('username');
table.string('password');
table.unique('username');
}),
knex.schema.createTable('identity', table => {
table.increments('id');
table.string('type');
table.string('value');
}),
knex.schema.createTable('identity_user', table => {
table.integer('user_id').references('user.id');
table.integer('identity_id').references('identity.id');
table.unique(['user_id', 'identity_id']);
})
]);

我的书架模型如下所示:

bookshelf.plugin([ 'registry', 'bookshelf-camelcase' ]);

const Identity = bookshelf.model('Identity', {
tableName: 'identity',

user() {
return this.belongsTo('User', 'identity_user');
}
});

const User = bookshelf.model('User', {
tableName: 'user',

initialize() {
this.on('saving', model => {
if (model.hasChanged('username')) {
return model.set('username', String(model.attributes.username).toLowerCase());
}
});
this.on('saving', model => {
if (model.hasChanged('password')) {
return bcrypt.hash(model.attributes.password, 10)
.then(hash => model.set('password', hash));
}
});
},

identities() {
return this.hasMany('Identity', 'identity_user');
}
});

在我的 createUser 函数中,我尝试在单个事务中插入新用户和身份。

function createUser(req, res, next) {
const { email, username, password } = req.body;

// some data validation

return bookshelf.transaction((t) => {
return new User({ username, password } ).save(null, { transacting: t })
.then(user => new Identity({ type: 'email', value: email }).save({ userId: user.attributes.id }, { transacting: t }))
.then(() => res.sendStatus(204))
.catch(err => {
// handle PostgreSQL unique violation error
});
});
}

当我运行服务器并尝试注册新用户时,出现以下错误:

insert into "identity" ("type", "user_id", "value") values ($1, $2, $3) returning "id" - column "user_id" of relation "identity" does not exist { error: insert into "identity" ("type", "user_id", "value") values ($1, $2, $3) returning "id" - column "user_id" of relation "identity" does not exist

这是一个 PostgreSQL 错误(代码 42703 - 未定义列),但一切似乎都设置正确。我真的可以用另一双眼睛来看待这个问题。我错过了什么?

提前致谢!

最佳答案

该错误是因为 Bookshelf 发现“userId”被插入到 Identity 中,并推断列名称为“user_id”。但要连接到 MxN 关系,您需要使用 attach()相反:

function createUser(req, res, next) {
const { email, username, password } = req.body;

// some data validation

return bookshelf.transaction((t) => {
return new User({ username, password } )
.save(null, { transacting: t })
.then(user => new Identity({ type: 'email', value: email })
.save(null, { transacting: t }))
.then(identity => user.identities()
.attach(identity.id, { transacting: t }));
})
.then(() => res.sendStatus(204))
.catch(err => {
// handle PostgreSQL unique violation error
});
}

似乎对我也有用的一种变体是直接附加模型(例如 .attach(identity, { transacting: t })),但文档不支持这种方法。

编辑我忽略了模型定义中的两个错误,hasMany() 仅在使用 through() 时映射到 MxN 关系> 调用,需要将连接表映射为模型。在上面的例子中,我认为使用简单的“belongsToMany()”调用就足够了。因此,将您的关系定义替换为:

user() {
return this.belongsToMany('User');
}

identities() {
return this.belongsToMany('Identity');
}

Edit2:将catch()移至事务范围之外,因此异常会自动触发回滚。

Edit3:扁平化的 then() 链和非数据库内容从事务范围中删除。

关于javascript - 插入事务后如何保存一对多关系,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43832862/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com