例子使用的是一个电影对象,需要存储电影基本信息:名称,简介,上映时间,剧照(一对多),电影类型(多对多),演员列表(多对多)
使用非托管事务方法:
//连接数据库
var Sequelize = require("sequelize");
var seq = new Sequelize('sequelize_demo', 'root', '654321', {
host: '127.0.0.1',
port: '3306',
dialect: "mysql",
dialectOptions: {
charset: 'utf8mb4'
},
timezone: process.env.TZ
});
async function createVideo({ videoname, videoinfourl, replacedatetime, v_id, address, coverimgurl, scenarioinfo, photolist, videotype, actorlist, writerlist, directorlist }) {
const videoInfo = await Video.findOne({
where: { v_id: v_id },
})
if (videoInfo) {//video已存在
return new ErrorModel(VideoDataIsExitInfo)
}
const video = {
videoname,
videoinfourl,
replacedatetime,
v_id,
address,
coverimgurl,
scenarioinfo: scenarioinfo,
}
//开始一个事务并将其保存到变量 t 中
const t = await seq.transaction();
try {
//正常create方法,直接在参数中加上{transaction:t}就可以了
let videoRes = await Video.create(video, {
transaction: t
})
if (photolist) {
let photos = []
for (let index = 0; index < photolist.length; index++) {
const imgurl = photolist[index];
const saveImgRes = await Photo.create({
imgurl
}, {
transaction: t
})
photos.push(saveImgRes)
}
//注意设置一对多关联关系时,也要加上
await videoRes.setPhotos(photos, { transaction: t })
}
// 处理类型标签
if (videotype) {
let types = []
for (let index = 0; index < videotype.length; index++) {
const type = videotype[index];
//findOrCreate方法再加参数时,不能在后面加,这个方法只支持一个参数,放到where和default这一级就好了
let res = await VideoType.findOrCreate({
where: {
typename: type
},
default: {
typename: type
},
transaction: t
})
types.push(res[0])
}
//注意设置关联时要加事务
await videoRes.setVideotypes(types, { transaction: t })
}
// 处理演员表
if (actorlist) {
let actors = []
for (let index = 0; index < actorlist.length; index++) {
const actor = actorlist[index];
const res = await Actor.findOrCreate({
where: {
actorname: actor.actorname,
actorheadurl: actor.actorheadurl
}, default: {
actorname: actor.actorname,
actorheadurl: actor.actorheadurl
},
transaction: t
})
actors.push(res)
}
await videoRes.addActors(actors, { transaction: t })
}
//都保存成功则提交
await t.commit();
return new SuccessModel(videoRes)
} catch (error) {
await t.rollback();
console.error(error.message, error.stack);
return new ErrorModel(createNewVideoDataFailInfo)
}
}
遇到的错误:
1、事务死锁:
ER_LOCK_WAIT_TIMEOUT: Lock wait timeout exceeded; try restarting transaction SequelizeDatabaseError: ER_LOCK_WAIT_TIMEOUT: Lock wait timeout exceeded; try restarting transaction
解决:查找整个事务中间是否有漏掉没有加事务的方法,比如我这个报错就是因为在添加多对多关联数据时,videoRes.addActors(actors)
这个方法没有加上事务导致的,修改如下:
await videoRes.addActors(actors, { transaction: t })
问题解决