我想使用pqxx :: work进行多次查询和承诺,而 commit 函数阻止我再次使用它。 这是一个简单的例子:
pqxx::connection G_connexion("dbname=basetest user=usertest password=1234");
pqxx::work G_work(G_connexion);
int main(int argc, char* argv[]) {
G_work.exec("insert into test.table1(nom) VALUES('foo');");
G_work.commit();//until here, no problem
G_work.exec("insert into test.table1(nom) VALUES('bar');"); //error, transaction already closed
G_work.commit();
}
当我尝试插入'bar'值时,在提交后,我得到一个pqxx :: usage_error:Error executing query . Attempt to activate transaction<READ COMMITTED> which is already closed
如何在提交更改后避免关闭连接?我可以用相当于G_work = pqxx :: work(G_connexion)或其他的成功重置G_work吗? 此外,一个错误的请求不应该崩溃整个过程,只是正在进行的过程(G_work在失败后仍然可用)。
我必须保留相同的变量G_Work,因为它将是一个从程序中很多地方调用的全局变量。
答案 0 :(得分:10)
pqxx::work
只是pqxx::transaction<>
,最终从pqxx::transaction_base
获得了大部分逻辑。
此课程不适用于多个交易。相反,它适用于try / catch块中的单个事务。它有一个状态成员变量(m_Status
),即使在提交后也永远不会重新初始化。
正常模式是:
{
pqxx::work l_work(G_connexion);
try {
l_work.exec("insert into test.table1(nom) VALUES('foo');");
l_work.commit();
} catch (const exception& e) {
l_work.abort();
throw;
}
}
可以说,libpqxx可以在删除时回滚事务(完全避免try / catch),但它没有。
似乎这并不适合您的使用模式,因为您希望G_work
成为可从程序中的多个位置访问的全局变量。请注意,pqxx :: work不是连接对象的类,而只是一种用C ++异常处理封装begin / commit / rollback的方法。
尽管如此,libpqxx还允许您在事务外执行语句(或至少在libpqxx管理的事务之外)。您应该使用pqxx::nontransaction
类的实例。
#include "pqxx/nontransaction"
pqxx::connection G_connexion("dbname=basetest user=usertest password=1234");
pqxx::nontransaction G_work(G_connexion);
int f() {
G_work.exec("insert into test.table1(nom) VALUES('foo');");
G_work.exec("insert into test.table1(nom) VALUES('bar');");
}
请注意,这相当于:
#include "pqxx/nontransaction"
pqxx::connection G_connexion("dbname=basetest user=usertest password=1234");
int f() {
pqxx::nontransaction l_work(G_connexion);
l_work.exec("insert into test.table1(nom) VALUES('foo');");
l_work.exec("insert into test.table1(nom) VALUES('bar');");
}
最终,无法阻止您使用pqxx::nontransaction
管理交易。如果你想要savepoints,情况尤其如此。如果您的交易意图超出功能范围(例如在全球范围内),我还建议您使用pqxx::nontransaction
。
#include "pqxx/nontransaction"
pqxx::connection G_connexion("dbname=basetest user=usertest password=1234");
pqxx::nontransaction G_work(G_connexion);
int f() {
G_work.exec("begin;");
G_work.exec("insert into test.table1(nom) VALUES('foo');");
G_work.exec("savepoint f_savepoint;");
// If the statement fails, rollback to checkpoint.
try {
G_work.exec("insert into test.table1(nom) VALUES('bar');");
} catch (const pqxx::sql_error& e) {
G_work.exec("rollback to savepoint f_savepoint;");
}
G_work.exec("commit;");
}