【问题标题】:Sequelize transaction Not doing rollback when error throwsSequelize transaction 抛出错误时不进行回滚
【发布时间】:2021-05-10 21:01:47
【问题描述】:

我正在使用 sequelize 事务(托管),当错误引发回滚并没有真正发生时,也许我在这里做错了什么?

我的测试用例:当代码块 2 抛出错误时,代码块 1 中所做的事情并没有回滚,请帮忙。

return sequelize.transaction(function (t) {
        return db.VenueTag.destroy({where: {venueId: venue.venueId}}, {transaction: t}).then(function () {
        }, {transaction: t}).then(function () {
        //block 1
            return db.VenueTag.upsert({
            ...
            });
        }, {transaction: t}).then(function () {
        //block 2
            //update venue details
            return venue.updateAttributes({
                ...
            },{ transaction: t});
        });
    }).then(function (result) {
        // Transaction has been committed
        // result is whatever the result of the promise chain returned to the transaction callback
        return res.status(200).json(result);
    }).catch(function (err) {
        // Transaction has been rolled back
        // err is whatever rejected the promise chain returned to the transaction callback
        return res.status(500).send({
            message: errorHandler.getErrorMessage(err)
        });
    });

【问题讨论】:

标签: node.js sequelize.js


【解决方案1】:

你的承诺链中有错误,试试这个:

return sequelize.transaction(function (t) {
    return db.VenueTag.destroy({where: {venueId: venue.venueId}}, {transaction: t})
    .then(function () {
    //block 1
        return db.VenueTag.upsert({
        ...
        }, {transaction: t});
    .then(function () {
    //block 2
        //update venue details
        return venue.updateAttributes({
            ...
        },{ transaction: t});
    });
}).then(function (result) {
    // Transaction has been committed
    // result is whatever the result of the promise chain returned to the transaction callback
    return res.status(200).json(result);
}).catch(function (err) {
    // Transaction has been rolled back
    // err is whatever rejected the promise chain returned to the transaction callback
    return res.status(500).send({
        message: errorHandler.getErrorMessage(err)
    });
});

【讨论】:

    【解决方案2】:

    如果您要迎合 ES7 受众或使用 node.js。您可以使用 async/await 方法来简化回调/承诺链:

        /*Global Setup*/
        let venue, db; // Whatever instances these are....
    
        async function deleteVenueTag () {
          let transaction;
          try {
            transaction = await sequelize.transaction();
            let VenueTag = await db.findOne({where: {venueId: venue.venueId}}, {transaction});
            if (VenueTag) {
              await VenueTag.destroy({ transaction });
              await VenueTag.upsert({ transaction });
              await venue.updateAttributes({ transaction });
              await transaction.commit();
            }
          } catch (error) {
            transaction.rollback();
          }
        }
    

    【讨论】:

    • 注意,如果 findOne 没有找到任何结果,则返回 null,因此在这种情况下会抛出 ... cannot destroy of null 错误。回滚在 catch 块中自动完成
    • 我认为这是一个错误github.com/sequelize/sequelize/issues/7665
    • 我现在看到这是一个错误,我一直在使用它,记住 findOne 在不匹配任何记录而不知道这是一个错误的情况下返回 null,很好! ....我的第一种方法确实是 findAll 限制为 1
    【解决方案3】:

    如果你在下面使用这样的东西

    return Users.update(updateUser, {
        where: {
            uid: sessionUser.uid,
            status: 'ACTIVE'
        },
        transaction: t     //second parameter is "options", so transaction must be in it
    })
    

    那么transaction是第二个options参数中的key,而不是第三个

    【讨论】:

      猜你喜欢
      • 2017-05-25
      • 2020-09-24
      • 2013-05-01
      • 2021-07-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-02-20
      • 2022-01-20
      相关资源
      最近更新 更多