pqxx重用/重新激活工作事务

时间:2014-10-20 11:01:44

标签: c++ postgresql libpqxx

我想使用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,因为它将是一个从程序中很多地方调用的全局变量。

1 个答案:

答案 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;");
}
相关问题