我们一直在尝试在Loopback中实现ACID事务而没有成功。文档中的唯一示例使用了'创建'方法。我们尝试完全覆盖事件以及操作挂钩的多种变体。我们只能使创建示例起作用。
核心要求:我们需要能够在特定模型的创建和更新方法中启动事务,然后更新事务中的多个表(使用Loopback的ORM函数)或者直接使用SQL),具有基于业务规则提交或回滚的能力。 例如,我们需要终点能够接受包含其标题和详细信息事务的发票,验证它,更新各种表(例如库存和客户),然后保存(或回滚)单一ACID交易中的所有变更。
使用数据库事务 https://docs.strongloop.com/display/public/LB/Using+database+transactions)
以下是文档中的示例:
Post.create({title: 't1', content: 'c1'}, {transaction: tx}, function(err, post) {
post.updateAttributes({content: 'c2', {transaction: tx}, function(err, newPost) {
//
newPost.reviews.create({content: 'r1'}, {transaction: tx}, function(err, newPost) {
});
}
});
操作挂钩: https://docs.strongloop.com/display/public/LB/Operation+hooks
我们只能成功覆盖一些核心方法:
Item.create = function(id, cb){
console.log('create'); // Success!
}
//
Item.find = function(id, cb){
console.log('find'); // Success!
}
Item.findById = function(id, cb){
console.log('findById'); // Success!
}
Item.getById = function(id, cb){
console.log('updateAttributes'); // Did not work!
}
Item.all = function(id, cb){
console.log('all'); // Did not work!
};
Item.findOrCreate = function(id, test, cb){
console.log('findOrCreate'); // Did not work!
}
Item.replicate = function(id, test, cb){
console.log('replicate'); // Did not work!
}
Item.save = function(id, test, cb){
console.log('save'); // Did not work!
}
Item.updateAll = function(id, test, cb){
console.log('updateAll'); // Did not work!
}
Item.upsert = function(id, test, cb){
console.log('upsert'); // Did not work!
}
Item.updateAttribute = function(id, cb){
console.log('updateAttribute'); // Did not work!
};
Item.updateById = function(id, test, cb){
console.log('updateById'); // Did not work!
}
在操作挂钩中实现保存,更新等也不起作用:
Item.observe('before save', function(ctx, next) {
console.log('before save');
ctx.Model.beginTransaction({isolationLevel: ctx.Model.Transaction.READ_COMMITTED}, function(err, tx) {
// Now we have a transaction (tx)
console.log('begin transaction', err);
//tx.commit(function(err) {
// console.log('commit', err);
//})
//tx.rollback(function(err) {
// console.log('rollback', err);
//})
next();
});
})
答案 0 :(得分:4)
我设法让交易有效,但我不知道这是否是最佳方式。 我需要检查"实例"因为当找不到用户时它不会返回错误,但实例为null。我使用内置的promises做到了,因为使用回调会非常难看。
在以下示例中,我必须找到两个用户才能更新它们。仅当两个值都已修改时,事务才会成功。如果在此期间发生一个错误,则应该停止事务(回滚)。
var firstUserInstance;
var secondUserInstance;
User.beginTransaction('READ COMMITTED', function(err, tx) {
// find first user and pass it to first 'then'
User.findById(firstUser.userId, {transaction: tx})
.then(function(instance){
if(instance){
firstUserInstance = instance;
//Pass second user instance to next 'then'
return User.findById(firstUser.userId, {transaction: tx});
}else{
throw ({message: "User not found", status: 400});
}
})
// Update first user
.then(function(instance){
if(instance){
secondUserInstance = instance;
//Update first user and pass result to next 'then'
return firstUserInstance.updateAttribute("attribute", "newValue", {transaction: tx});
}else{
throw ({message: "User 'toUserId' not found", status: 400});
}
})
// Update second user
.then(function(instance){
if(instance){
//Update second user and pass result to next 'then'
return secondUserInstance.updateAttribute("attribute", "newValue", {transaction: tx});
}else{
throw ({message: "Error updating", status: 401});
}
})
.then(function(instance){
if(instance){
//Everything went OK - commit changes
console.log(instance);
tx.commit(function(err){});
}else{
throw ({message: "Error updating", status: 401});
}
})
.catch(function(err){
//Something happened - Any thrown errors will end here - rollback changes
console.log(err);
tx.rollback(function(err){});
});
});
我对此并不完全满意,我认为还有更好的方法,但我希望这有帮助!