2016-01-23 25 views
2

我們一直試圖在環回中實現ACID事務,但未取得成功。文檔中的唯一示例使用「創建」方法。我們已經嘗試完全覆蓋事件以及操作掛鉤的多種變體。我們只能得到創建的例子才能工作。如何在環回中實現ACID事務

核心訴求:我們需要能夠(與SQL或者使用回送的ORM功能或直接)開始在創建和更新方法交易的具體型號,然後在交易中更新多個表與能力基於業務規則進行提交或回滾。例如例如,我們需要端點能夠接受包含其頭和明細交易的發票,驗證它,更新各種表(如庫存和客戶),然後保存(或回滾)所有更改一個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

到目前爲止,我們一直無法找到任何完整的文檔(包括Loopback文檔)或使用Loopback的完整ACID事務的任何完整示例。此功能是否實際完全發佈? – ASA2

+0

經過很多挫折之後,我們決定不使用Loopback中的數據庫事務功能,並實施了Knex SQL查詢生成器。 Knex有一個非常好的,獨立於數據庫的接口,支持多表交易。 – ASA2

+0

嗨,我評論只是爲了添加loopback 2文檔的新鏈接:http://loopback.io/doc/en/lb2/Using-database-transactions.html和http://loopback.io/doc/en /lb2/Operation-hooks.html –

回答

3

我已經得到了一個交易的工作,但我不知道這是不是最好的辦法做到這一點。 我需要檢查「實例」,因爲當找不到用戶時,它不會返回錯誤,但實例爲空。我使用內置的承諾做了它,因爲使用回調會很糟糕。

在下面的例子中,我必須找到兩個用戶才能更新它們。只有在兩個值都被修改的情況下,交易才能成功。如果在此期間發生了一個錯誤,則應該停止該事務(回滾)。

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){}); 
     }); 

    }); 

我對此並不完全滿意,我認爲還有更好的辦法,但我希望這有助於!