在PostgreSQL中使用SOCI C ++禁用自动提交功能

时间:2019-06-18 05:28:48

标签: c++ postgresql autocommit soci

无论如何,这是一个答案,而不是我需要在 SO 中提出的问题。我一直在努力解决这个问题(“在PostgreSQL数据库中使用soci库时如何关闭自动提交”),并提出了几种解决方案。

在Oracle中,默认情况下,自动提交选项处于关闭状态,我们必须显式调用soci::session::commit来提交已完成的事务,但是在PostgreSQL中,这是另一种方法,它将在执行后立即提交一条sql语句(如果我错了,请纠正我)。当我们独立编写应用程序数据库时,这将带来问题。社会图书馆提供soci::transaction来解决这个问题。

因此,当我们通过向其提供soci::transaction来初始化soci::session时,它将保存我们进行的事务而无需提交数据库。最后,当我们调用soci::transaction::commit时,它将把更改提交到数据库。

soci::session sql(CONNECTION_STRING);
soci::transaction tr(sql);
try {
    sql << "insert into soci_test(id, name) values(7, \'John\')";
    tr.commit();
}
catch (std::exception& e) {
    tr.rollback();
}

但是,执行commitrollback将结束交易tr,我们需要初始化另一个soci::transaction以便保留将来的交易(以创建正在进行的交易交易)。这是有关soci::transaction的更多有趣事实。

  1. 每个soci::transaction只能有一个soci::session实例。如果初始化另一个,第二个将替换第一个。
  2. 使用commit不能执行多个rollbacksoci::transaction。您将在第二次提交或回滚时收到异常。
  3. 您可以初始化transaction,然后使用session::commitsession::rollback。它将得到与transaction::committransaction::rollback相同的结果。但是,一旦您照常执行单次提交或回滚,事务将立即结束。
  4. soci::transaction对象对于您的范围(在其中执行sql并调用commit或rollback)以保持您所做的数据库事务直到显式提交或回滚之前的可见性都没有关系。换句话说,如果transaction中有一个活动的session正在运行,则数据库事务将一直保留,直到我们显式提交或回滚为止。
  5. 但是,如果为transaction创建的session实例的生命周期结束了,我们就不能指望数据库事务会暂停。
  6. 如果每个人都遭受“警告:没有正在进行的事务”,则您只需要使用soci::transaction::commitsoci::transaction::rollback来执行提交或回滚。

现在,我将发布我想出的解决方案,以便对任何数据库后端启用显式提交或回滚。

1 个答案:

答案 0 :(得分:0)

这是我想出的解决方案。

namespace mysociutils
{
    class session : public soci::session
    {
    public:
        void open(std::string const & connectString)
        {
            soci::session::open(connectString);
            tr = std::unique_ptr<soci::transaction>(new soci::transaction(*this));
        }

        void commit()
        {
            tr->commit();
            tr  = std::unique_ptr<soci::transaction>(new soci::transaction(*this));
        }

        void rollback()
        {
            tr->rollback();
            tr  = std::unique_ptr<soci::transaction>(new soci::transaction(*this));
        }        

        void ~session()
        {
            tr->rollback();
        }

    private:
        std::unique_ptr<soci::transaction> tr;
    };
}

执行提交或回滚后,请初始化一个新的soci::transaction。现在,您可以将soci::session sql替换为mysociutils::session sql,并享受SET AUTOCOMMIT OFF