如何在交易中使用其他回购

时间:2019-07-05 07:44:04

标签: node.js pg-promise

我有几种方法的存储库,其中一些方法使用事务(.tx)。 例如,在下面的我的DevicesRepository中,“ add”方法必须插入一个新的Device,这意味着: 1.插入一个系统并返回ID(SystemsRepository) 2.插入带有返回器systemId的设备并获取新的ID 3.插入使用deviceId的其他片段(其他存储库)

我的问题是,在该事务中,我不知道如何访问其他回购方法。 我可以使用数据库对象中的其他存储库(Database.systems.add,Database.OtherRepo.add,[...]),但是如果我这样做了

tx doc

  

在根数据库对象上调用该方法时,该方法从池中分配连接,执行回调,完成后-将连接释放回池中。但是,在另一个任务或事务中调用该方法时,该方法会重用父级连接。

task doc

  

一次执行多个请求时,一个请求只能分配和释放一次连接,同时在同一连接会话中执行所有必需的查询。更重要的是,交易只能在单个连接中进行。

谢谢! :)

P.S:我可以添加如何初始化数据库和存储库

./ db / repos / devices.js

'use strict';

var Database = null, pgp = null, Collections = null;

async function add(params) {
  // I can use Database.systems.add
  return Database.tx('Insert-New-Device', async function(transaction) {
    let device = params.data.device;

    const system = await transaction.systems.add(params);
    device.systemid = system.systemId;

    const query = pgp.helpers.insert(device, Collections.insert);
    query += " RETURNING deviceId";
    device.deviceId = await transaction.one(query);

    const OtherRepoInsert = await transaction.otherRepos.add(params);
    device.otherRepos.id = OtherRepoInsert.otherReposId;

    return device
  })
  .then(data => { return data; })
  .catch(ex => { throw new Error(ex); });
}

function createColumnsets() { /* hidden for brevity (almost the same as the pg-promise-demo */ }

const DevicesRepository = {
  add: add
};


module.exports = (db) => {
  Database = db;
  pgp = db.$config.pgp;
  Collections = createColumnsets();

  return DevicesRepository;
}

./ db / repos / systems.js

'use strict';

var Database = null, pgp = null, Collections = null;

async function add(params) {
  var system = params.data.system;
  system.archid=2;
  system.distributionid=3;

  var query = pgp.helpers.insert(system, Collections.insert);
  if(params.return) query += " RETURNING *";

  return Database.any(query)
                  .then(data => { return data; })
                  .catch(ex => { throw new Error(ex); });
}

function createColumnsets() { /* hidden for brevity (almost the same as the pg-promise-demo */ }

const SystemsRepository = {
  add: add
};

module.exports = (db) => {
  Database = db;
  pgp = db.$config.pgp;
  Collections = createColumnsets();

  return SystemsRepository;
}

3 个答案:

答案 0 :(得分:0)

我找到了真正的问题。

如果转到我的第一篇文章,您会看到我的每个仓库都导出了一个初始化函数: 1.由pg-promise'extend'事件调用 2.需要一个参数:上下文 3.使用此参数在db。$ config.pgp

中初始化存储库中的“ pgp”变量

demo中所述,当第一次在应用程序中以及每个任务和事务中加载数据库时,就会发生此事件。

就我而言: 事件第一次发生(完整的应用程序初始化)时,事件的参数'obj'是database context(包含$ config,$ pool等),因此可以正常工作 当事件发生在任务或事务中时,事件的参数'obj'是Task context,其中$ config不存在,因此事件无法使用我的存储库扩展上下文。引发了一个异常“无法读取未定义的属性帮助器”,但未出现并且不会使我的应用程序崩溃,我不知道为什么,也许是在事件中被捕获了。这就是为什么我不能在交易中使用我的仓库。

我像这样修改了我的代码,它起作用了:

./ db / index.js

'use strict';
/* hidden for brevity */
// pg-promise initialization options:
const initOptions = {
    promiseLib: promise,
    extend(obj, dc) {
        obj.roles = repos.Roles(obj, pgp);
        obj.shells = repos.Shells(obj, pgp);
        obj.systems = repos.Systems(obj, pgp);
        obj.devices = repos.Devices(obj, pgp);
    }
};

const pgp = require('pg-promise')(initOptions);
const db = pgp(config);

/* hidden for brevity */

./ db / index.js

'use strict';
/* hidden for brevity */
// pg-promise initialization options:
const initOptions = {
    promiseLib: promise,
    extend(obj, dc) {
        obj.roles = repos.Roles(obj, pgp);
        obj.shells = repos.Shells(obj, pgp);
        obj.systems = repos.Systems(obj, pgp);
        obj.devices = repos.Devices(obj, pgp);
    }
};

const pgp = require('pg-promise')(initOptions);
const db = pgp(config);

/* hidden for brevity */

./ db / repos / {repoFiles} .js

/* hidden for brevity */
module.exports = (db, pgpLib) => {
  Database = db;
  pgp = pgpLib;
  Collections = createColumnsets();

  return DevicesRepository;
}

答案 1 :(得分:0)

属性$config用于集成。这就是为什么它仅存在于根Database级别,而不存在于任务或事务内部的原因。

为了利用helpers命名空间,应在初始化存储库时将pgp传递到存储库中,如pg-promise-demo所示:

 extend(obj, dc) {
        obj.users = new repos.Users(obj, pgp);
        obj.products = new repos.Products(obj, pgp);
    }

答案 2 :(得分:-1)

您可以在调用之外建立事务,然后将其传递给那些函数以使他们使用它。

也就是说,我建议您使用一个稍微高级的查询构建器库,例如Knex.js,以免于这些(以及将来)令人头疼的麻烦。