Это скорее ответ, чем вопрос, который мне все равно нужно сформулировать в SO .Я долго боролся с этим вопросом («как отключить автокоммит при использовании библиотеки soci с базами данных PostgreSQL») и придумал несколько решений.
В Oracle по умолчанию опция автоматической фиксации отключена, и нам нужно явно вызвать soci::session::commit
, чтобы зафиксировать транзакции, которые мы сделали, но в PostgreSQL это происходит наоборот, и он будет зафиксирован, как только мывыполнить SQL-оператор (поправьте меня, если я не прав).Это создаст проблемы, когда мы создадим базу данных приложений самостоятельно.Библиотека soci предоставляет 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();
}
Но выполнение commit
или rollback
завершит транзакцию tr
, и нам нужно инициализировать другуюsoci::transaction
для удержания будущих транзакций (для создания активной транзакции в процессе), которую мы собираемся сделать.Вот более забавные факты о soci::transaction
.
- Вы можете иметь только один
soci::transaction
экземпляр на soci::session
.Второй заменит первый, если вы инициализируете другой. - Вы не можете выполнить более одного
commit
или rollback
, используя soci::transaction
.Вы получите исключение при втором коммите или откате. - Вы можете инициализировать
transaction
, затем использовать session::commit
или session::rollback
.Это даст тот же результат, что и transaction::commit
или transaction::rollback
.Но транзакция завершится, как только вы выполните обычную фиксацию или откат как обычно. - Не имеет значения видимость объекта
soci::transaction
для вашей области (где вы выполняете sql и вызываете commit или rollback), чтобы удерживать транзакции БД, которые вы сделали, до явного подтверждения или отката.Другими словами, если для session
идет активный transaction
, транзакции в дБ будут удерживаться до тех пор, пока мы явно не зафиксируем или не откатаемся. - Но, если время жизни экземпляра
transaction
, который создалпоскольку session
был окончен, мы не можем ожидать, что транзакции БД будут остановлены. - Если вы все страдаете от «ПРЕДУПРЕЖДЕНИЕ: транзакция не выполняется», вы должны выполнять фиксацию или откат только с помощью
soci::transaction::commit
или soci::transaction::rollback
.
Теперь я опубликую решение, которое я придумала, чтобы включить явную фиксацию или откат с любым бэкэндом базы данных.