在Postgres的Sequelize中使用Transaction

时间:2016-01-16 02:43:46

标签: postgresql transactions sequelize.js

我正在尝试noodejs中的sequelize事务。我使用postgres作为我的数据库。当我调用testDel时,事务会在testDel中自动提交。即使事务自动提交已经设置为false。

如果我将变量t从Db.transaction传递给testDel,那么它将等待手动提交/回滚。 我可以不通过功能吗?它使编码变得非常复杂。

编码如下:

Db.transaction({autocommit: false}).then((t) => {
    args = {vcTitle: {$ilike: '%ulie%'}};
    let boDelete = true;
    testDelPost(t, args)
    .then(rersult =>{
        if(rersult){
            t.commit();
        }else{
            t.rollback();
        }
    })
});             

function testDel(args){
    //the result got deleted and auto committed after this destroy, it 
    //doesn't wait for the above transaction to decide the commit or rollback.
    //If I pass t, and set traction: t in the destroy, then it work as expected
    return Db.models.Post.destroy({where: args})
    .then(result =>{
        if(result > 0){
            return true;
        }else{
            return false;
        }
    })
    .error(status =>{
        return error;
    })
}

1 个答案:

答案 0 :(得分:1)

使用Continuation Local Storage。这会将全局级Sequelize包分配给"命名空间",以便从中创建的所有实例在执行事务时引用命名空间。

您按照以下方式初始化Sequelize(假设ES6导入语法):

// Grab packages we need

import Sequelize from 'sequelize';
import Cls from 'continuation-local-storage';    

// Assign namespace to database

Sequelize.cls = Cls.createNamespace('db');

然后,这允许您在不明确传递t的情况下执行事务。它还会回滚未捕获的异常(或技术上未解决的承诺),并承诺解决的承诺:

以下是我在生产代码中使用的示例函数,该函数演示了该概念的实际应用。

它... ...

  • 启动事务(PostgreSQL中的BEGIN;
  • 创建一个新帐户(INSERT INTO "accounts"...
  • 创建将帐户加入帐户类型(INSERT INTO "account_type_accounts"...
  • 的条目
  • 创建将用户链接到帐户(INSERT INTO "users_accounts"...
  • 的条目
  • 如果上述所有内容都成功(COMMIT;),则仅执行插入。如果没有,它会回滚(ROLLBACK;

以下是代码:

createAccount (user, accountType, query = {}) {
  // Start transaction
  return this.db.connection.transaction(() => {
    // Create the new account
    return this.db.models.Account.create(query).then(account => {
      // Associate with user & account type
      return P.all([user.addAccount(account), accountType.addAccount(account)]).then(()=> {
        // Return account back up the promise chain
        return account;
      });
    });
  });
}

请注意缺少t变量或显式回滚/提交。