首页 > 解决方案 > nodejs, pg-promise:最佳存储库模式

问题描述

我在为我的 API 选择存储库模式时遇到了一些麻烦。数据库由几个表组成,这些表可以分为两个“部分”。

我是为每个表(第一个示例)做一个存储库还是每个“部分”(第二个示例)只做一个存储库?另一件需要注意的事情是,稍后(在某个月,当 API 的版本 1 生效时),API 将不得不同时管理一个额外的(NoSQL)数据库,而不是代替第一个(示例使用pg-承诺)

第一个例子

first.js : 只管理表'first'

'use strict';
class FirstRepository {
  constructor(/*parameters*/) { /* hidden for brevity */ }

  makeInsertQuery(params) {
    return this.pgp.helpers.insert(params, this.Collections.insert);
    // return query like `INSERT INTO first...`
  }

  // t.* = *Repository (FirstRepository, secondRepository, ...)
  insertOne(params) {
    return this.Database.tx('MyTag', async t => {
      let result = {};

      const query = t.first.makeInsertQuery(params) + " RETURNING *";
      result.first = await t.one(query);
      result.second = await t.second.insertOne(params);
      result.third = await t.third.insert(params);
      // some other call like that

      /**
       * LATER = INSERT IN THE OTHER DATABASE
       */

      return result;
    })
    .catch(ex => {
      throw ex;
    });
  }

  /* some other function, hidden for brevity */
}

module.exports = FirstRepository

second.js : 只管理表'second'

'use strict';
class SecondsRepository {
  constructor(/*parameters*/) { /* hidden for brevity */ }

  makeInsertQuery(params) {
    return this.pgp.helpers.insert(params, this.Collections.insert);
    // return query like `INSERT INTO second...`
  }

  insertOne(params) {
    let second = /* some stuf, hidden for brevity */;
    
    var query = this.makeInsertQuery(second);
    return this.Database.one(query)
            .then(data => { return data; })
            .catch(ex => { throw ex; });
  }

  /* some other function, hidden for brevity */
}

module.exports = SecondsRepository

第二个例子

// repo1.js
'use strict';
/* FirstPartRepository manage several tables : 'first', 'second' and 'third' */
class FirstPartRepository {
  constructor(/*parameters*/) { /* hidden for brevity */ }

  makeInsertQuery(params, entity) {
    let obj = /* extract it from params */
    return this.pgp.helpers.insert(params, this.Collections[entity].insert);
    // return query like `INSERT INTO ${entity}...`
  }

  // In this example, FirstPartRepository manage some table : 'first', 'second' and 'third'
  insertOne(params) {
    return this.Database.tx('MyTag', async t => {
      let result = {};

      const insertFirst  = t.firstpart.makeInsertQuery(params, 'first')  + " RETURNING *",
            insertSecond = t.firstpart.makeInsertQuery(params, 'second') + " RETURNING *",
            insertThird  = t.firstpart.makeInsertQuery(params, 'third')  + " RETURNING *";

      result.first  = await t.one(insertFirst);
      result.second = await t.one(insertSecond);
      result.third  = await t.one(insertThird);
      // some other like that

      /**
       * LATER = INSERT IN THE OTHER DATABASE
       */

      return result;
    })
    .catch(ex => {
      throw ex;
    });
  }

  /* some other function, hidden for brevity */
}

module.exports = FirstPartRepository

标签: node.jsrepository-patternpg-promise

解决方案


模式Repository= 对单个实体的一组操作。

在您的情况下,每个存储库都是一个代表单个表上所有操作的类。

在实现复杂的多实体业务逻辑时,您可以通过以下三种方式之一来实现它:

  • 您可以让密钥存储库实现高级业务方法
  • 您可以创建一个额外的高级存储库以保持高级逻辑分离
  • 您可以在存储库模式之外实现它,例如在外部函数中。

选择哪一个 - 取决于应用程序要求及其业务逻辑。


推荐阅读