问题
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;
})
}
回答1:
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.
来源:https://stackoverflow.com/questions/34822981/using-transaction-in-sequelize-for-postgres