插入或更新获取 "Transaction query already complete"
Insert or Updated getting "Transaction query already complete"
如何正确地在数据库中搜索一行,并根据搜索结果INSERT
/UPDATE
(INSERT
如果没有找到,UPDATE
如果找到)?
我目前正在这样做:
bookshelf.transaction(async function (t) {
for (var x = 0; x < 10; x++) {
let row = pmsParser.getRow(x);
if (_.isEmpty(row)) {
break;
}
let data = {
lastUpdate: moment(row.lastUpdate, 'DD/MM/YYYY - HH:mm').toDate(),
mvs: row.version,
color: row.color,
location: row.location,
status: row.status
};
new Vehicle({ chassi: row.chassi })
.fetch({ require: true })
.then(model => {
return new Vehicle(model)
.save(data, { transacting: t, patch: true });
})
.catch(Vehicle.NotFoundError, err => {
new Vehicle(data)
.save('chassi', row.chassi, { transacting: t })
.then(() => {
console.log(`Inserted... ${row.chassi}`);
});
})
.catch(err => {
console.log(err.message);
});
}
})
.catch(function (err) {
console.error(err);
return res.json({ status: false, count: 0, error: err.message });
});
我收到此错误:
Transaction query already complete, run with DEBUG=knex:tx for more info
Unhandled rejection Error: Transaction query already complete, run with DEBUG=knex:tx for more info
at completedError (/home/node/app/node_modules/knex/lib/transaction.js:297:9)
at /home/node/app/node_modules/knex/lib/transaction.js:266:22
at tryCatcher (/home/node/app/node_modules/bluebird/js/release/util.js:16:23)
at Function.Promise.attempt.Promise.try (/home/node/app/node_modules/bluebird/js/release/method.js:39:29)
at Client_SQLite3.trxClient.query (/home/node/app/node_modules/knex/lib/transaction.js:264:34)
at Runner.<anonymous> (/home/node/app/node_modules/knex/lib/runner.js:138:36)
at Runner.tryCatcher (/home/node/app/node_modules/bluebird/js/release/util.js:16:23)
at Runner.query (/home/node/app/node_modules/bluebird/js/release/method.js:15:34)
at /home/node/app/node_modules/knex/lib/runner.js:61:21
at tryCatcher (/home/node/app/node_modules/bluebird/js/release/util.js:16:23)
at /home/node/app/node_modules/bluebird/js/release/using.js:185:26
at tryCatcher (/home/node/app/node_modules/bluebird/js/release/util.js:16:23)
at Promise._settlePromiseFromHandler (/home/node/app/node_modules/bluebird/js/release/promise.js:512:31)
at Promise._settlePromise (/home/node/app/node_modules/bluebird/js/release/promise.js:569:18)
at Promise._settlePromise0 (/home/node/app/node_modules/bluebird/js/release/promise.js:614:10)
at Promise._settlePromises (/home/node/app/node_modules/bluebird/js/release/promise.js:693:18)
Knex 调试输出
knex:tx trx1: Starting top level transaction +0ms
knex:tx trx1: releasing connection +28ms
knex:tx undefined: Transaction completed: update "vehicles" set "color" = ?, "lastUpdate" = ?, "location" = ?, "mvs" = ?, "status" = ? where "id" = ? +15ms
Transaction query already complete, run with DEBUG=knex:tx for more info
knex:tx undefined: Transaction completed: update "vehicles" set "color" = ?, "lastUpdate" = ?, "location" = ?, "mvs" = ?, "status" = ? where "id" = ? +8ms
Transaction query already complete, run with DEBUG=knex:tx for more info
在事务下所有 相关的数据库访问必须在事务的上下文中。
//...
new Vehicle({ chassi: row.chassi })
.fetch({ require: true, transacting: t })
.then(model => {
//...
您的迭代没有得到正确的承诺。这会使您的更改转义事务上下文,从而导致 'Transaction query already complete' 错误。在循环中创建承诺时,始终建议收集它们并提交给承诺集合处理,例如 Promise.all()
。这将避免在解决所有承诺之前转义事务上下文。
这些更改可能会导致如下代码(未测试):
bookshelf.transaction(async function (t) {
let promises = [];
for (var x = 0; x < 10; x++) {
let row = pmsParser.getRow(x);
if (_.isEmpty(row)) {
break;
}
let data = {
lastUpdate: moment(row.lastUpdate, 'DD/MM/YYYY - HH:mm').toDate(),
mvs: row.version,
color: row.color,
location: row.location,
status: row.status
};
promises.push(
new Vehicle({ chassi: row.chassi })
.fetch({ require: true, transacting: t })
.then(model => {
return model // no need to use 'new Vehicle()' here
.save(data, { transacting: t, patch: true });
})
.catch(Vehicle.NotFoundError, err => {
return new Vehicle(data) // missing 'return'
.save('chassi', row.chassi, { transacting: t })
.then(() => {
console.log(`Inserted... ${row.chassi}`);
});
})
.catch(err => {
console.log(err.message);
// throw err; // should rethrow it!
})
);
}
return Promise.all(promises)
.catch(function (err) {
console.error(err);
return res.json({ status: false, count: 0, error: err.message });
});
};
如何正确地在数据库中搜索一行,并根据搜索结果INSERT
/UPDATE
(INSERT
如果没有找到,UPDATE
如果找到)?
我目前正在这样做:
bookshelf.transaction(async function (t) {
for (var x = 0; x < 10; x++) {
let row = pmsParser.getRow(x);
if (_.isEmpty(row)) {
break;
}
let data = {
lastUpdate: moment(row.lastUpdate, 'DD/MM/YYYY - HH:mm').toDate(),
mvs: row.version,
color: row.color,
location: row.location,
status: row.status
};
new Vehicle({ chassi: row.chassi })
.fetch({ require: true })
.then(model => {
return new Vehicle(model)
.save(data, { transacting: t, patch: true });
})
.catch(Vehicle.NotFoundError, err => {
new Vehicle(data)
.save('chassi', row.chassi, { transacting: t })
.then(() => {
console.log(`Inserted... ${row.chassi}`);
});
})
.catch(err => {
console.log(err.message);
});
}
})
.catch(function (err) {
console.error(err);
return res.json({ status: false, count: 0, error: err.message });
});
我收到此错误:
Transaction query already complete, run with DEBUG=knex:tx for more info
Unhandled rejection Error: Transaction query already complete, run with DEBUG=knex:tx for more info
at completedError (/home/node/app/node_modules/knex/lib/transaction.js:297:9)
at /home/node/app/node_modules/knex/lib/transaction.js:266:22
at tryCatcher (/home/node/app/node_modules/bluebird/js/release/util.js:16:23)
at Function.Promise.attempt.Promise.try (/home/node/app/node_modules/bluebird/js/release/method.js:39:29)
at Client_SQLite3.trxClient.query (/home/node/app/node_modules/knex/lib/transaction.js:264:34)
at Runner.<anonymous> (/home/node/app/node_modules/knex/lib/runner.js:138:36)
at Runner.tryCatcher (/home/node/app/node_modules/bluebird/js/release/util.js:16:23)
at Runner.query (/home/node/app/node_modules/bluebird/js/release/method.js:15:34)
at /home/node/app/node_modules/knex/lib/runner.js:61:21
at tryCatcher (/home/node/app/node_modules/bluebird/js/release/util.js:16:23)
at /home/node/app/node_modules/bluebird/js/release/using.js:185:26
at tryCatcher (/home/node/app/node_modules/bluebird/js/release/util.js:16:23)
at Promise._settlePromiseFromHandler (/home/node/app/node_modules/bluebird/js/release/promise.js:512:31)
at Promise._settlePromise (/home/node/app/node_modules/bluebird/js/release/promise.js:569:18)
at Promise._settlePromise0 (/home/node/app/node_modules/bluebird/js/release/promise.js:614:10)
at Promise._settlePromises (/home/node/app/node_modules/bluebird/js/release/promise.js:693:18)
Knex 调试输出
knex:tx trx1: Starting top level transaction +0ms
knex:tx trx1: releasing connection +28ms
knex:tx undefined: Transaction completed: update "vehicles" set "color" = ?, "lastUpdate" = ?, "location" = ?, "mvs" = ?, "status" = ? where "id" = ? +15ms
Transaction query already complete, run with DEBUG=knex:tx for more info
knex:tx undefined: Transaction completed: update "vehicles" set "color" = ?, "lastUpdate" = ?, "location" = ?, "mvs" = ?, "status" = ? where "id" = ? +8ms
Transaction query already complete, run with DEBUG=knex:tx for more info
在事务下所有 相关的数据库访问必须在事务的上下文中。
//...
new Vehicle({ chassi: row.chassi })
.fetch({ require: true, transacting: t })
.then(model => {
//...
您的迭代没有得到正确的承诺。这会使您的更改转义事务上下文,从而导致 'Transaction query already complete' 错误。在循环中创建承诺时,始终建议收集它们并提交给承诺集合处理,例如 Promise.all()
。这将避免在解决所有承诺之前转义事务上下文。
这些更改可能会导致如下代码(未测试):
bookshelf.transaction(async function (t) {
let promises = [];
for (var x = 0; x < 10; x++) {
let row = pmsParser.getRow(x);
if (_.isEmpty(row)) {
break;
}
let data = {
lastUpdate: moment(row.lastUpdate, 'DD/MM/YYYY - HH:mm').toDate(),
mvs: row.version,
color: row.color,
location: row.location,
status: row.status
};
promises.push(
new Vehicle({ chassi: row.chassi })
.fetch({ require: true, transacting: t })
.then(model => {
return model // no need to use 'new Vehicle()' here
.save(data, { transacting: t, patch: true });
})
.catch(Vehicle.NotFoundError, err => {
return new Vehicle(data) // missing 'return'
.save('chassi', row.chassi, { transacting: t })
.then(() => {
console.log(`Inserted... ${row.chassi}`);
});
})
.catch(err => {
console.log(err.message);
// throw err; // should rethrow it!
})
);
}
return Promise.all(promises)
.catch(function (err) {
console.error(err);
return res.json({ status: false, count: 0, error: err.message });
});
};