NodeJS使用Sequelize 使用事务时,各方法的传参方式

例子使用的是一个电影对象,需要存储电影基本信息:名称,简介,上映时间,剧照(一对多),电影类型(多对多),演员列表(多对多)

使用非托管事务方法:

//连接数据库
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 })

问题解决

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值