Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
270 views
in Technique[技术] by (71.8m points)

postgresql - Using Transaction in Sequelize for Postgres

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.

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.

The coding is as following:

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;
    })
}
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

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.

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

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.

It...

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

Here's the code:

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

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


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...