如何使用 sequelize 事务删除多个不同的数据以及 express.js 中的某些条件?
How to use a sequelize transaction to delete multiple different data along with some conditions in express.js?
我正在为在线汽车销售制作 API。我需要使用 sequelize 事务同时删除一些关于汽车销售的数据。有2个条件。首先,如果汽车已售出,那么我需要更新汽车状态,但同时创建购买和反馈数据。如果某辆车已经在其他地方出售,那么我需要删除这辆车,以及该车的浏览量、点赞数和议价数据,并创建有关该车销售情况的反馈。
例如,如果需要删除的汽车的第 3 条数据违反约束(导致错误),则删除该汽车的第 1 条和第 2 条数据将与任何删除的 /创建数据。
我尝试过使用 sequelize 事务,但即使有任何数据尚未删除它也会提交(导致错误)
这是已经制作好的代码。
async function deleteCarAsAdmin(req, res) {
let error = [];
try {
// id, reasonType, comment, price, paymentMethod, buyerUserType, sellDate
const { deleteData } = req.body;
const trans = await sequelize.transaction();
const lengtData = deleteData.length;
function customForEach(callback) {
const array = this;
let index = 0;
const next = () => {
index++;
if (array.length > 0) {
callback(array.shift(), index, next);
}
};
next();
}
Array.prototype.customForEachFunc = customForEach;
const promise = await new Promise((resolve, reject) => {
const resRej = (errlength, lengtData, deleteDatalength) => {
if (errlength == lengtData) {
return reject({ message: error });
}
if (deleteDatalength == 0) {
return resolve();
}
};
deleteData.customForEachFunc(async (data, index, next) => {
const carData = await models.Car.findByPk(data.id, { transaction: trans });
if (!carData) {
apiResponse._redconsole(`GA KETEMU BANG / Car Id ${data.id} Not Found`);
error.push(`carID : ${data.id} Not Found`);
console.log(`index : ${index}`);
console.log(`length ${deleteData.length}`);
console.log(error);
resRej(error.length, lengtData, deleteData);
return next();
}
if (validator.isInt(data.id ? data.id.toString() : '') === false) {
apiResponse._redconsole(`Car Id ${data.id} MustBe Integer`);
error.error.push('Id Must Be an Integer,\n');
resRej(error.length, lengtData, deleteData);
return next();
}
if (!data.reasonType) {
apiResponse._redconsole(`Please Provide Your Reason For Deleting carId ${data.id}!`);
error.push(`carID : ${data.id} Please Provide Your Reason For Deleting carId ${data.id}`);
resRej(error.length, lengtData, deleteData);
return next();
}
let regex = /^(?!\s*$).+/;
if (!data.comment || !regex.test(data.comment)) {
apiResponse._redconsole(`Please Provide Your Comment For Deleting carId ${data.id}!`);
error.push(`Please Provide Your Coment For Deleting carId ${data.id}`);
resRej(error.length, lengtData, deleteData);
return next();
}
let reasonId = null;
const getReasonType = await models.ReasonType.findOne(
{
where: { typeReason: data.reasonType },
attributes: ['id']
},
{ transaction: trans }
).catch(async err => {
apiResponse._redconsole(err.message`1`);
error.push(`${err.message}\n`);
resRej(error.length, lengtData, deleteData);
return next();
});
if (getReasonType) {
reasonId = getReasonType.id;
}
const now = moment(data.sellDate)
.tz('Asia/Jakarta')
.format('YYYY-MM-DD HH:mm:ss');
if (data.reasonType === 1) {
if (!data.price) {
apiResponse._redconsole(`Please Provide Your Price For CarId ${data.id}`);
error.push(`Please Provide Your Price For carId ${data.id},\n`);
resRej(error.length, lengtData, deleteData);
return next();
}
if (!data.paymentMethod) {
apiResponse._redconsole(`Please Provide Your Payment Method For CarId ${data.id}`);
error.push(`Please Provide Your Payment Method For carId ${data.id},\n`);
resRej(error.length, lengtData, deleteData);
return next();
}
if (!data.sellDate) {
apiResponse._redconsole(`Please Provide Your Payment Date For CarId ${data.id}`);
error.push(`Please Provide Your Payment Date For carId ${data.id},\n`);
resRej(error.length, lengtData, deleteData);
return next();
}
if (!data.buyerUserType) {
apiResponse._redconsole(`Please Provide Your Type Of Customer For CarId ${data.id}`);
error.push(`Please Provide Your Type Of Customer For carId ${data.id},\n`);
resRej(error.length, lengtData, deleteData);
return next();
}
await models.Purchase.create(
{
userId: carData.userId,
carId: data.id,
price: data.price,
paymentMethod: data.paymentMethod
},
{ transaction: trans }
).then(async datas => {
//update car status
await datas
.update(
{
status: 2
},
{
where: { id: datas.carId }
},
{ transaction: trans }
)
.catch(async err => {
apiResponse._redconsole(`${err.message} carId ${data.id}`);
error.push(` ${err.message},\n`);
await trans.rollback();
resRej(error.length, lengtData, deleteData);
return next();
});
//create feedback
await models.FeedBack.create(
{
carId: data.id,
userId: carData.userId,
reasonType: reasonId,
comment: data.comment,
paymentMethod: data.paymentMethod == 0 ? 'kredit' : 'tunai',
buyerUserType: data.buyerUserType,
sellDate: now
},
{ transaction: trans }
).catch(async err => {
apiResponse._redconsole(`${err.message} carId ${data.id}`);
error.push(` ${err.message},\n`);
await trans.rollback();
resRej(error.length, lengtData, deleteData);
return next();
});
await models.Car.destroy(
{
where: { id: data.id }
},
{ transaction: trans }
).catch(async err => {
apiResponse._redconsole(`${err.message} carId ${data.id}`);
error.push(` ${err.message},\n`);
await trans.rollback();
resRej(error.length, lengtData, deleteData);
return next();
});
});
} else if (data.reasonType == 2) {
//create feedback
await models.FeedBack.create(
{
carId: data.id,
userId: carData.userId,
reasonType: reasonId,
comment: data.comment
},
{ transaction: trans }
).catch(async err => {
apiResponse._redconsole(`${err.message} carId ${data.id}`);
error.push(` ${err.message},\n`);
resRej(error.length, lengtData, deleteData);
await trans.rollback();
return next();
});
//delete car
await models.Car.destroy(
{
where: { id: data.id }
},
{ transaction: trans }
).catch(async err => {
apiResponse._redconsole(`${err.message} carId ${data.id}`);
error.push(` ${err.message},\n`);
resRej(error.length, lengtData, deleteData);
await trans.rollback();
return next();
});
//delete bargain
const bargainData = await models.Bargain.findOne({
where: {
carId: data.id
}
});
if (bargainData) {
await models.Bargain.destroy(
{
where: { carId: data.id }
},
{ transaction: trans }
).catch(async err => {
apiResponse._redconsole(`${err.message} carId ${data.id}`);
error.push(` ${err.message},\n`);
await trans.rollback();
resRej(error.length, lengtData, deleteData);
return next();
});
}
//delete like
console.log('delete like');
const likeData = await models.Like.findOne({
where: {
carId: data.id
}
});
if (likeData) {
await models.Like.destroy(
{
where: { carId: data.id }
},
{ transaction: trans }
).catch(async err => {
apiResponse._redconsole(`${err.message} carId ${data.id}`);
error.push(` ${err.message},\n`);
await trans.rollback();
resRej(error.length, lengtData, deleteData);
return next();
});
}
//delele view
console.log('delete view');
console.log(data.id);
const viewData = await models.View.findOne({
where: {
carId: data.id
}
});
console.log(viewData);
if (viewData) {
await models.View.destroy(
{
where: { carId: data.id }
},
{ transaction: trans }
).catch(async err => {
apiResponse._redconsole(`${err.message} carId ${data.id}`);
error.push(` ${err.message},\n`);
await trans.rollback();
resRej(error.length, lengtData, deleteData);
return next();
});
}
}
resRej(error.length, lengtData, deleteData);
return next();
});
});
await trans.commit();
return res.status(200).json({
success: true
});
} catch (err3) {
return res.status(500).json({
success: false,
errors: err3.message
});
}
}
请帮忙。谢谢,抱歉英文不好
至少我注意到你混淆了 await
和 then/catch
。仅使用 await
并在需要时将其包装到 try/catch
中。
同样在 await datas.update
中,您应该在第二个参数中指定 transaction
而不是在第三个参数中:
await datas
.update(
{
status: 2
},
{
where: { id: datas.carId },
transaction: trans
}
)
destroy
也是如此:
await models.Car.destroy(
{
where: { id: data.id },
transaction: trans
}
)
...
await models.Bargain.destroy(
{
where: { carId: data.id },
transaction: trans
}
)
...
await models.Like.destroy(
{
where: { carId: data.id },
transaction: trans
}
)
...
await models.View.destroy(
{
where: { carId: data.id },
transaction: trans
}
)
并且您忘记在 findOne
中指明交易:
const bargainData = await models.Bargain.findOne({
where: {
carId: data.id
},
transaction: trans
})
...
const likeData = await models.Like.findOne({
where: {
carId: data.id
},
transaction: trans
})
...
const viewData = await models.View.findOne({
where: {
carId: data.id
},
transaction: trans
});
我正在为在线汽车销售制作 API。我需要使用 sequelize 事务同时删除一些关于汽车销售的数据。有2个条件。首先,如果汽车已售出,那么我需要更新汽车状态,但同时创建购买和反馈数据。如果某辆车已经在其他地方出售,那么我需要删除这辆车,以及该车的浏览量、点赞数和议价数据,并创建有关该车销售情况的反馈。
例如,如果需要删除的汽车的第 3 条数据违反约束(导致错误),则删除该汽车的第 1 条和第 2 条数据将与任何删除的 /创建数据。
我尝试过使用 sequelize 事务,但即使有任何数据尚未删除它也会提交(导致错误)
这是已经制作好的代码。
async function deleteCarAsAdmin(req, res) {
let error = [];
try {
// id, reasonType, comment, price, paymentMethod, buyerUserType, sellDate
const { deleteData } = req.body;
const trans = await sequelize.transaction();
const lengtData = deleteData.length;
function customForEach(callback) {
const array = this;
let index = 0;
const next = () => {
index++;
if (array.length > 0) {
callback(array.shift(), index, next);
}
};
next();
}
Array.prototype.customForEachFunc = customForEach;
const promise = await new Promise((resolve, reject) => {
const resRej = (errlength, lengtData, deleteDatalength) => {
if (errlength == lengtData) {
return reject({ message: error });
}
if (deleteDatalength == 0) {
return resolve();
}
};
deleteData.customForEachFunc(async (data, index, next) => {
const carData = await models.Car.findByPk(data.id, { transaction: trans });
if (!carData) {
apiResponse._redconsole(`GA KETEMU BANG / Car Id ${data.id} Not Found`);
error.push(`carID : ${data.id} Not Found`);
console.log(`index : ${index}`);
console.log(`length ${deleteData.length}`);
console.log(error);
resRej(error.length, lengtData, deleteData);
return next();
}
if (validator.isInt(data.id ? data.id.toString() : '') === false) {
apiResponse._redconsole(`Car Id ${data.id} MustBe Integer`);
error.error.push('Id Must Be an Integer,\n');
resRej(error.length, lengtData, deleteData);
return next();
}
if (!data.reasonType) {
apiResponse._redconsole(`Please Provide Your Reason For Deleting carId ${data.id}!`);
error.push(`carID : ${data.id} Please Provide Your Reason For Deleting carId ${data.id}`);
resRej(error.length, lengtData, deleteData);
return next();
}
let regex = /^(?!\s*$).+/;
if (!data.comment || !regex.test(data.comment)) {
apiResponse._redconsole(`Please Provide Your Comment For Deleting carId ${data.id}!`);
error.push(`Please Provide Your Coment For Deleting carId ${data.id}`);
resRej(error.length, lengtData, deleteData);
return next();
}
let reasonId = null;
const getReasonType = await models.ReasonType.findOne(
{
where: { typeReason: data.reasonType },
attributes: ['id']
},
{ transaction: trans }
).catch(async err => {
apiResponse._redconsole(err.message`1`);
error.push(`${err.message}\n`);
resRej(error.length, lengtData, deleteData);
return next();
});
if (getReasonType) {
reasonId = getReasonType.id;
}
const now = moment(data.sellDate)
.tz('Asia/Jakarta')
.format('YYYY-MM-DD HH:mm:ss');
if (data.reasonType === 1) {
if (!data.price) {
apiResponse._redconsole(`Please Provide Your Price For CarId ${data.id}`);
error.push(`Please Provide Your Price For carId ${data.id},\n`);
resRej(error.length, lengtData, deleteData);
return next();
}
if (!data.paymentMethod) {
apiResponse._redconsole(`Please Provide Your Payment Method For CarId ${data.id}`);
error.push(`Please Provide Your Payment Method For carId ${data.id},\n`);
resRej(error.length, lengtData, deleteData);
return next();
}
if (!data.sellDate) {
apiResponse._redconsole(`Please Provide Your Payment Date For CarId ${data.id}`);
error.push(`Please Provide Your Payment Date For carId ${data.id},\n`);
resRej(error.length, lengtData, deleteData);
return next();
}
if (!data.buyerUserType) {
apiResponse._redconsole(`Please Provide Your Type Of Customer For CarId ${data.id}`);
error.push(`Please Provide Your Type Of Customer For carId ${data.id},\n`);
resRej(error.length, lengtData, deleteData);
return next();
}
await models.Purchase.create(
{
userId: carData.userId,
carId: data.id,
price: data.price,
paymentMethod: data.paymentMethod
},
{ transaction: trans }
).then(async datas => {
//update car status
await datas
.update(
{
status: 2
},
{
where: { id: datas.carId }
},
{ transaction: trans }
)
.catch(async err => {
apiResponse._redconsole(`${err.message} carId ${data.id}`);
error.push(` ${err.message},\n`);
await trans.rollback();
resRej(error.length, lengtData, deleteData);
return next();
});
//create feedback
await models.FeedBack.create(
{
carId: data.id,
userId: carData.userId,
reasonType: reasonId,
comment: data.comment,
paymentMethod: data.paymentMethod == 0 ? 'kredit' : 'tunai',
buyerUserType: data.buyerUserType,
sellDate: now
},
{ transaction: trans }
).catch(async err => {
apiResponse._redconsole(`${err.message} carId ${data.id}`);
error.push(` ${err.message},\n`);
await trans.rollback();
resRej(error.length, lengtData, deleteData);
return next();
});
await models.Car.destroy(
{
where: { id: data.id }
},
{ transaction: trans }
).catch(async err => {
apiResponse._redconsole(`${err.message} carId ${data.id}`);
error.push(` ${err.message},\n`);
await trans.rollback();
resRej(error.length, lengtData, deleteData);
return next();
});
});
} else if (data.reasonType == 2) {
//create feedback
await models.FeedBack.create(
{
carId: data.id,
userId: carData.userId,
reasonType: reasonId,
comment: data.comment
},
{ transaction: trans }
).catch(async err => {
apiResponse._redconsole(`${err.message} carId ${data.id}`);
error.push(` ${err.message},\n`);
resRej(error.length, lengtData, deleteData);
await trans.rollback();
return next();
});
//delete car
await models.Car.destroy(
{
where: { id: data.id }
},
{ transaction: trans }
).catch(async err => {
apiResponse._redconsole(`${err.message} carId ${data.id}`);
error.push(` ${err.message},\n`);
resRej(error.length, lengtData, deleteData);
await trans.rollback();
return next();
});
//delete bargain
const bargainData = await models.Bargain.findOne({
where: {
carId: data.id
}
});
if (bargainData) {
await models.Bargain.destroy(
{
where: { carId: data.id }
},
{ transaction: trans }
).catch(async err => {
apiResponse._redconsole(`${err.message} carId ${data.id}`);
error.push(` ${err.message},\n`);
await trans.rollback();
resRej(error.length, lengtData, deleteData);
return next();
});
}
//delete like
console.log('delete like');
const likeData = await models.Like.findOne({
where: {
carId: data.id
}
});
if (likeData) {
await models.Like.destroy(
{
where: { carId: data.id }
},
{ transaction: trans }
).catch(async err => {
apiResponse._redconsole(`${err.message} carId ${data.id}`);
error.push(` ${err.message},\n`);
await trans.rollback();
resRej(error.length, lengtData, deleteData);
return next();
});
}
//delele view
console.log('delete view');
console.log(data.id);
const viewData = await models.View.findOne({
where: {
carId: data.id
}
});
console.log(viewData);
if (viewData) {
await models.View.destroy(
{
where: { carId: data.id }
},
{ transaction: trans }
).catch(async err => {
apiResponse._redconsole(`${err.message} carId ${data.id}`);
error.push(` ${err.message},\n`);
await trans.rollback();
resRej(error.length, lengtData, deleteData);
return next();
});
}
}
resRej(error.length, lengtData, deleteData);
return next();
});
});
await trans.commit();
return res.status(200).json({
success: true
});
} catch (err3) {
return res.status(500).json({
success: false,
errors: err3.message
});
}
}
请帮忙。谢谢,抱歉英文不好
至少我注意到你混淆了 await
和 then/catch
。仅使用 await
并在需要时将其包装到 try/catch
中。
同样在 await datas.update
中,您应该在第二个参数中指定 transaction
而不是在第三个参数中:
await datas
.update(
{
status: 2
},
{
where: { id: datas.carId },
transaction: trans
}
)
destroy
也是如此:
await models.Car.destroy(
{
where: { id: data.id },
transaction: trans
}
)
...
await models.Bargain.destroy(
{
where: { carId: data.id },
transaction: trans
}
)
...
await models.Like.destroy(
{
where: { carId: data.id },
transaction: trans
}
)
...
await models.View.destroy(
{
where: { carId: data.id },
transaction: trans
}
)
并且您忘记在 findOne
中指明交易:
const bargainData = await models.Bargain.findOne({
where: {
carId: data.id
},
transaction: trans
})
...
const likeData = await models.Like.findOne({
where: {
carId: data.id
},
transaction: trans
})
...
const viewData = await models.View.findOne({
where: {
carId: data.id
},
transaction: trans
});