首页 > 解决方案 > 如何创建 sequelize 事务以保存 deeplu 嵌套对象

问题描述

如果我有这样的对象要保存:

{
    "objA": {
        "attr1": 123,
        "attr2": "dummy str",
   },
   "objB": [
        {
            "attr1": true,
            "attr2": [ // this a list of objC's
                {"attr1": 123, "attr2": false},
                {"attr1": 456, "attr2": true},
            ]
        },
        {
            "attr1": false,
            "attr2": [ // this a list of objC's
                {"attr1": 789, "attr2": true},
                {"attr1": 101, "attr2": true},
            ]
        },
    ]
}

关系如下:

  1. objA 有很多 objB
  2. objB 属于 objA
  3. objB 有很多 objC
  4. objC 属于 objB

Sequelize 文档在这一点上太浅了,它只展示了如何保存一个简单的对象。所以这就是我一直在尝试但没有成功:

const {objA, objB} = req.body;

return db.sequelize.transaction((t) => {
  return objA.create(
    {
      attr1,
      attr2,
      index,
    },
    { transaction: t }
  ).then((newObjA) => {      
    objB.forEach((obj) => {
      return objB.create(
        { ...obj, objA_id: newObjA.id },
        { transaction: t }
      ).then((newObjB) => {            
        objB.attr2.forEach((obj) => {
          return objC.create(
            { ...obj, objB_id: newObjB.id },
            { transaction: t }
            ).then((newObjC) => {
              return newObjB.addObjC(newObjC, {
                transaction: t,
              }).then(() => {
                  return newObjA.addObjB(newObjB);
              });
            });
          });
        });
      });
    });
  }).then(() => {
    res.status(200).json({ MSG: "SAVE_SUCCESS" });
  }).catch((err) => {
    res.status(500).json({ MSG: "SAVE_ERROR" });
});

标签: javascripttransactionssequelize.js

解决方案


您不应该将 forEach 与异步函数一起使用(forEach 用于同步迭代)。像这样使用forawait

// assuming ObjA, ObjB, ObjC are registered sequelize models
return db.sequelize.transaction(async t => {
  const newObjA = await ObjA.create(
    {
      attr1,
      attr2,
      index,
    },
    { transaction: t })
  for (const obj of objB) {
    const newObjB = await ObjB.create(
        { ...obj, objA_id: newObjA.id },
        { transaction: t })
    for (const attr of newObjB.attr2) {
      const newObjC = await ObjC.create(
            { ...attr, objB_id: newObjB.id },
            { transaction: t })
      await newObjB.addObjC(newObjC, {
                transaction: t,
              })
    }
    // you forgot to indicate transaction here in the original code
    await newObjA.addObjB(newObjB, { transaction: t }) 
  }
})

推荐阅读