我正在尝试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;
})
}
答案 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
的情况下执行事务。它还会回滚未捕获的异常(或技术上未解决的承诺),并承诺解决的承诺:
以下是我在生产代码中使用的示例函数,该函数演示了该概念的实际应用。
它... ...
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
变量或显式回滚/提交。