从knex交易中区分knex客户端

问题描述

基于Knex承诺的交易可以像常规knex客户端一样使用。

const db = knex.transaction() //or just const db = require('knex')(knexOptions)
db('books').insert(books);    // it works in both case

我需要接受knex对象作为函数的参数,并在其中执行事务。如果knex对象或knex事务作为参数传递,我能以某种方式区分吗?如果这不是事务,我想用knex.transaction包装客户端对象。

我可以使用类似db.isTransaction的语法吗?

function myFunc(db) {
if (!db.isTransaction)
  {
    db=knex.transaction()
  }
db('books').insert(books); 
}

解决方法

虽然没有使用Knex库对此进行本机实现,但是您可以轻松创建条件语句来检查连接是否是事务性的。

话虽如此,您的实现无法正常工作,因为.transaction()方法不会返回数据库实例,而是将实例传递给回调函数:

db.transaction((transactionObject) => {
    transactionObject('books').insert(books);
})

您可以如下调整代码:

function myFunc(db) {
  // If instance is not a transaction,create one
  if (db && !('commit' in db) && !('rollback' in db)) {
    db.transaction(async function (trx) {
      // Perform the query on the new transactional database connection
      await trx('books').insert(books);
    })

  // Otherwise,perform it on the ALREADY transactional database connection
  } else {
    db('books').insert(books);
  }
});

这可能是最简单的解决方案,因为它仅使用本机JavaScript in运算符来检查连接上是否存在仅对事务可用的方法。我不是knexpert(不好意思),但这是我认为可以做到的最干净的方法。

,

使用 knex.isTransaction 属性判断对象是 knex 事务还是客户端。

function myFunction(db) {
  if (db.isTransaction) {
    console.log('Inside transaction')
    return db.from('table_1').select()
  } else {
    console.log('Wrapping client in a transaction')
    return db.transaction(trx => myFunction(trx))
  }
}

在这两种情况下,您的查询都应该在事务中执行