Sequelize 事务的使用与Transaction类

TransactionSequelize中用于实现事务功能的子类,通过调用Sequelize.transaction()方法可以创建一个该类的实例。在Sequelize中,支持自动提交/回滚,也可以支持用户手动提交/回滚。


1. 事务的使用

Sequelize有两种使用事务的方式:

基于Promise结果链的自动提交/回滚

另一种是不自动提交和回滚,而由用户控制事务

 

1.1 受管理的事务(auto-callback)

受管理的事务会自动提交或回滚,你可以向sequelize.transaction方法传递一个回调函数来启动一个事务。

需要注意,在这种方式下传递给回调函数的transaction会返回一个promise链,在promise链中(thencatch)中并不能调用t.commit()t.rollback()来控制事务。在这种方式下,如果使用事务的所有promise链都执行成功,则自动提交;如果其中之一执行失败,则自动回滚。

return sequelize.transaction(function (t) {

  // 要确保所有的查询链都有return返回
  return User.create({
    firstName: 'Abraham',
    lastName: 'Lincoln'
  }, {transaction: t}).then(function (user) {
    return user.setShooter({
      firstName: 'John',
      lastName: 'Boothe'
    }, {transaction: t});
  });

}).then(function (result) {
  // Transaction 会自动提交
  // result 是事务回调中使用promise链中执行结果
}).catch(function (err) {
  // Transaction 会自动回滚
  // err 是事务回调中使用promise链中的异常结果
});

抛出错误并回滚

使用受管理的事务时,不能通过手工调用的方式来提交或回滚事务。但在需要时(如验证失败),可以通过throw来抛出异常回滚事务。

return sequelize.transaction(function (t) {
  return User.create({
    firstName: 'Abraham',
    lastName: 'Lincoln'
  }, {transaction: t}).then(function (user) {
    // 注意,虽然所有操作成功但仍会回滚
    throw new Error();
  });
});



1.2 不受管理的事务(then-callback)

不受管理的事务需要你强制提交或回滚,如果不进行这些操作,事务会一直保持挂起状态直到超时。

启动一个不受管理的事务,同样是调用sequelize.transaction()方法,但不传递回调函数参数(仍然可以传递选项参数)。然后可以在其返回的promisethen方法中手工控制事务:

return sequelize.transaction().then(function (t) {
  return User.create({
    firstName: 'Homer',
    lastName: 'Simpson'
  }, {transaction: t}).then(function (user) {
    return user.addSibling({
      firstName: 'Lisa',
      lastName: 'Simpson'
    }, {transaction: t});
  }).then(function () {
    return t.commit();
  }).catch(function (err) {
    return t.rollback();
  });
});

 

1.5 选项参数

调用transaction方法时,可以向其第一个参数中传递一个选项参数,通过该参数可以对事务进行一些配置:

return sequelize.transaction({ /* options */ });

默认配置选项如下:

{
  autocommit: true,
  isolationLevel: 'REPEATABLE_READ',
  deferrable: 'NOT DEFERRABLE' // implicit default of postgres
}

isolationLevel选项可以在初始化Sequelize全局设置,也可以启动每个事务时局部设置:

// 全局设置
new Sequelize('db', 'user', 'pw', {
  isolationLevel: Sequelize.Transaction.ISOLATION_LEVELS.SERIALIZABLE
});

// 局部设置
sequelize.transaction({
  isolationLevel: Sequelize.Transaction.ISOLATION_LEVELS.SERIALIZABLE
});

deferrable选项会在事务执行前或执行后启动一个额外的查询,但需要注意此选项仅适用于PostgreSQL

sequelize.transaction({
  // to defer all constraints:
  deferrable: Sequelize.Deferrable.SET_DEFERRED,

  // to defer a specific constraint:
  deferrable: Sequelize.Deferrable.SET_DEFERRED(['some_constraint']),

  // to not defer constraints:
  deferrable: Sequelize.Deferrable.SET_IMMEDIATE
})

 

2. Transaction

2.1 访问与初始化

Transaction对象用于标识一个要执行的事务,可以通过以下方式创建该对象的实例:

sequelize.transaction(options, autoCallback);    // sequelize 是一个Sequelize对象实例

在创建事务实例,并在事务中执行查询时,需要传入一个可选参数对象。各参数值如下:

名称 类型 说明

sequelize Sequelize 一个已配置的sequelize实例

options Object 选项对象

options.autocommit=true Boolean 设置事务的

autocommit(自动完成)

属性

options.type=true String 设置事务类型,详见TYPES options.isolationLevel=true String 设置事务的隔离级别,详见ISOLATION_LEVELS

options.deferrable String 设置立即或延迟检查约束 TYPES

此选项仅Sqlite适用,用于设置事务类型,默认为DEFERRED,也可以在new Sequelize()时由options.transactionType选项指定。可选值如下:

{
  DEFERRED: "DEFERRED",
  IMMEDIATE: "IMMEDIATE",
  EXCLUSIVE: "EXCLUSIVE"
}

我可以像下面这样设置事务类型:

return sequelize.transaction({
  type: Sequelize.Transaction.EXCLUSIVE
}, function (t) {

 // 事务

}).then(function(result) {
  // 事务已完成(commit)
}).catch(function(err) {
  // 出现异常
});

ISOLATION_LEVELS

通过options.isolationLevel选项设置sequelize.transaction启动事务时的隔离级别。默认为REPEATABLE_READ,也可以在new Sequelize()时由options.isolationLevel选项指定。可选值如下:

{
  READ_UNCOMMITTED: "READ UNCOMMITTED",
  READ_COMMITTED: "READ COMMITTED",
  REPEATABLE_READ: "REPEATABLE READ",
  SERIALIZABLE: "SERIALIZABLE"
}

如,可以像下面这样设置事务的隔离级别:

return sequelize.transaction({
  isolationLevel: Sequelize.Transaction.SERIALIZABLE
}, function (t) {

 // 事务

}).then(function(result) {
  // 事务已完成(commit)
}).catch(function(err) {
  // 出现异常
});

 

2.2 实例方法

通过sequelize.transaction()启动事务后,在实例中包含两个方法commit()rollback()分别用于完成事务和事务回滚。

commit()完成事务

该方法用于手动完成事务。

如,我们可以像下面这样完成一个事务:

sequelize.transaction(function (t) {
  // 事务
  Model.findAll().then(function(result){
    // 手动提交/完成事务
    t.commit();
  });
}).then(function(result) {
  // 事务已完成(commit)
}).catch(function(err) {
  // 出现异常
});

rollback()回滚事务

该方法用于手动回滚事务。

sequelize.transaction(function (t) {
  // 事务
  Model.findAll().then(function(result){
    // 手动回滚事务
    t.rollback();
  });
}).then(function(result) {
  // 事务已完成(commit)
}).catch(function(err) {
  // 出现异常
});

 

在 Async/Await 中使用事务

let transaction;    

try {
  // get transaction
  transaction = await sequelize.transaction();

  // step 1
  await Model.destroy({where: {id}, transaction});

  // step 2
  await Model.create({}, {transaction});

  // commit
  await transaction.commit();

} catch (err) {
  // Rollback transaction if any errors were encountered
  await transaction.rollback();
}




来源:

https://itbilu.com/nodejs/npm/EJO6CcCM-.html

https://stackoverflow.com/questions/42870374/node-js-7-how-to-use-sequelize-transaction-with-async-await/43342688

https://cnodejs.org/topic/5b126d3c8a4f51e140d944a3

声明:本站所有文章和图片,如无特殊说明,均为原创发布。商业转载请联系作者获得授权,非商业转载请注明出处。
真诚赞赏,手留余香
赞赏
随机推荐
WordPress RESTful API 路由代码结构
TypeScript 和 Koa 实践
Light 主题
Linux netstat 命令
JavaScript 检查 Date 是否为 Invalid Date
用 JavaScript 实现数字增加滚动动画
二分查找法
Flame 插件