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

声明:本站所有文章和图片,如无特殊说明,均为原创发布。商业转载请联系作者获得授权,非商业转载请注明出处。
随机推荐
版权相关
Git push 错误:Updates were rejected because the remote contains work that you do not have locally
JavaScript 原生拖放
JavaScript 数据类型和变量
WordPress 使用 shortcode() 增加编辑器功能
MySQL 数据库中货币单位如何存储
JavaScript 流程控制语句
RESTful API 执行 delete 返回204无法获取 Body