在Sequelize for Postgres中使用事务 [英] Using Transaction in Sequelize for Postgres

查看:99
本文介绍了在Sequelize for Postgres中使用事务的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试在noodejs中进行续集交易。我正在使用postgres作为数据库。当我调用testDel时,事务将自动提交到testDel中。即使事务自动提交已设置为false。

I am trying the transaction for sequelize in noodejs. I am using postgres as my database. When I call the testDel the transaction get autocommitted in the testDel. Even if transaction autocommit already set to false.

如果我将变量t从Db.transaction传递给testDel,则它将等待手动提交/回滚。
我可以不将t传递给函数吗?

If I pass the variable t from the Db.transaction to testDel, then it will wait for the manual commit / rollback. Can I do without passing t into function? It make coding very complicated.

编码如下:

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;
    })
}


推荐答案

使用继续本地存储。这会将全局级别的Sequelize包分配给一个命名空间,以便从其创建的所有实例在执行事务时都引用该命名空间。

Use Continuation Local Storage. This assigns the global-level Sequelize package to a "namespace", so that all instances created from it reference the namespace when performing transactions.

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

You initialise Sequelize as follows (assuming ES6 import syntax):

// Grab packages we need

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

// Assign namespace to database

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

然后,您可以执行交易而无需显式传递 t 。它还回滚未捕获的异常(或技术上未解决的承诺),并提交已解决的承诺:

This then allows you to perform transactions without explicitly passing t around. It also rolls back on uncaught exceptions (or technically, unresolved promises), and commits on resolved promises:

以下是我在生产代码中使用的示例函数,

The following is a sample function I'm using in production code that demonstrates the concept in action.

它...


  • 开始交易( BEGIN; 在PostgreSQL中)

  • 创建一个新帐户(插入帐户 ...

  • 创建一个将帐户加入帐户类型的条目( INSERT INTO account_type_accounts ...

  • 创建将用户链接到帐户的条目(插入 users_accounts ...

  • 仅在以上所有条件均获得成功时执行插入( COMMIT; )。如果不是,它将回滚( ROLLBACK;

  • Starts a transaction (BEGIN; in PostgreSQL)
  • Creates a new account (INSERT INTO "accounts"...)
  • Creates an entry that joins an account to an account type (INSERT INTO "account_type_accounts"...)
  • Creates an entry that links the user to an account (INSERT INTO "users_accounts"...)
  • Only performs the inserts if ALL of above succeeded (COMMIT;). If not, it rolls back (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 变量或显式回滚/提交。

Note the lack of t variables or explicit rollback/commit.

这篇关于在Sequelize for Postgres中使用事务的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆