问题描述
基于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))
}
}
在这两种情况下,您的查询都应该在事务中执行