在 Postgres 的 Sequelize 中使用事务
Using Transaction in Sequelize for Postgres
我正在尝试在 noodejs 中进行 sequelize 事务。我正在使用 postgres 作为我的数据库。当我调用 testDel 时,事务会在 testDel 中自动提交。即使事务自动提交已经设置为 false。
如果我将变量 t 从 Db.transaction 传递给 testDel,那么它将等待手动提交/回滚。
我可以不将 t 传递给函数吗?它使编码变得非常复杂。
编码如下:
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;
})
}
使用Continuation Local Storage。这会将 global-level Sequelize 包分配给 "namespace",以便从中创建的所有实例在执行事务时都引用命名空间。
你初始化 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;
在 PostgreSQL 中)
- 创建一个新帐户(
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
变量或显式 rollback/commit。
我正在尝试在 noodejs 中进行 sequelize 事务。我正在使用 postgres 作为我的数据库。当我调用 testDel 时,事务会在 testDel 中自动提交。即使事务自动提交已经设置为 false。
如果我将变量 t 从 Db.transaction 传递给 testDel,那么它将等待手动提交/回滚。 我可以不将 t 传递给函数吗?它使编码变得非常复杂。
编码如下:
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;
})
}
使用Continuation Local Storage。这会将 global-level Sequelize 包分配给 "namespace",以便从中创建的所有实例在执行事务时都引用命名空间。
你初始化 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;
在 PostgreSQL 中) - 创建一个新帐户(
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
变量或显式 rollback/commit。