Transaction
是Sequelize
中用于实现事务功能的子类,通过调用Sequelize.transaction()
方法可以创建一个该类的实例。在Sequelize
中,支持自动提交/回滚,也可以支持用户手动提交/回滚。
1. 事务的使用
Sequelize有两种使用事务的方式:
基于Promise结果链的自动提交/回滚
另一种是不自动提交和回滚,而由用户控制事务
1.1 受管理的事务(auto-callback)
受管理的事务会自动提交或回滚,你可以向sequelize.transaction
方法传递一个回调函数来启动一个事务。
需要注意,在这种方式下传递给回调函数的transaction
会返回一个promise
链,在promise
链中(then
或catch
)中并不能调用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