Russian Qt Forum
Ноябрь 01, 2024, 10:28 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: [1]   Вниз
  Печать  
Автор Тема: QMutexLocker паттерн для QSqlDatabase::transaction()  (Прочитано 7620 раз)
asvil
Гость
« : Январь 14, 2011, 20:40 »

Маленький класс для автороллбэка либо коммита.
Не используйте для ORACLE DDL.
header
Код:
#ifndef AUTOTRANSACTION_H
#define AUTOTRANSACTION_H

#include <QtSql/QSqlDatabase>

class AutoTransaction
{
public:
    AutoTransaction(const QSqlDatabase &db = QSqlDatabase::database());
    virtual ~AutoTransaction();
    virtual void commit();
private:
    QSqlDatabase db;
    bool needCommit;
};

#endif // AUTOTRANSACTION_H

source
Код:
#include "autotransaction.h"

AutoTransaction::AutoTransaction(const QSqlDatabase &database) :
  db(database)
{
  needCommit = db.transaction();
}

AutoTransaction::~AutoTransaction()
{
  if (needCommit)
    db.rollback();
}

void AutoTransaction::commit()
{
  if (needCommit) {
    db.commit();
    needCommit = false;
  }
}
Использование:
Код:
AutoTransaction transaction(ourDatabase);

foreach(const QString &line, lines) {
  ...
  QSqlQuery query(ourDatabase);
  query.exec("INSERT ....");
  if (corruptedFile) {
    return;
  }
  ...
}
transaction.commit();
Своровал у друга.
« Последнее редактирование: Январь 17, 2011, 22:34 от Филоненко Михаил » Записан
White Owl
Гость
« Ответ #1 : Январь 14, 2011, 20:57 »

Простите, а чем не устраивает просто посылать commit/roolback?
Код:
QSqlDatabase::database().commit();
или даже
Код:
qry.driver().transactionCommit();
Записан
Пантер
Administrator
Джедай : наставник для всех
*****
Offline Offline

Сообщений: 5876


Жаждущий знаний


Просмотр профиля WWW
« Ответ #2 : Январь 14, 2011, 21:07 »

Ну, так уж точно не забудешь перед return сделать роллбэк.
Записан

1. Qt - Qt Development Frameworks; QT - QuickTime
2. Не используйте в исходниках символы кириллицы!!!
3. Пользуйтесь тегом code при оформлении сообщений.
asvil
Гость
« Ответ #3 : Январь 15, 2011, 00:11 »

Ага, Пантер, верно подсказывает. Простите неправильно записал пример использования.
Код:
AutoTransaction transaction(ourDatabase);

foreach(const QString &line, lines) {
  ...
  QSqlQuery query(ourDatabase);
  query.exec("INSERT ....");
  if (corruptedFile) {
    ...
    return;
  }
  if (anotherFlag) {
    ...
    if (smthWrong) {
          .......
              if ().........
                    ........
                     
                     ... if ().....
                           return;

                     if ()
                             return;
                return;
 ..............................return;
       
    }
  }
  ...
}
transaction.commit();
Хотя, оспорте, а то так неинтересно.
Записан
White Owl
Гость
« Ответ #4 : Январь 15, 2011, 02:44 »

Хотя, оспорте, а то так неинтересно.
А запросто Улыбающийся

Код:
AutoTransaction transaction(ourDatabase);
QSqlQuery query(ourDatabase);
if(! query.execute("insert ..." ) ) return;
transaction.commit();
if(! query.execute("update ... ") return;  // Что будет?
transaction.commit();  // будет ли что-то?
убери переменную needCommit и всегда запрашивай существование транзакции.
Записан
MoPDoBoPoT
Гость
« Ответ #5 : Январь 15, 2011, 12:02 »

А ещё в Oracle есть такая особенность: после выполнения DDL оператора, происходит неявный коммит.
Записан
ритт
Гость
« Ответ #6 : Январь 15, 2011, 19:25 »

зачем оно виртуал?
и зачем оно не инлайновое?
Записан
asvil
Гость
« Ответ #7 : Январь 17, 2011, 22:34 »

Константин, авторское java-style решение:)
Павлик, спасибо уточнил сферу применения.
White Owl, а как запрашивать существование транзакции?
Записан
White Owl
Гость
« Ответ #8 : Январь 18, 2011, 19:49 »

White Owl, а как запрашивать существование транзакции?
а... select @@trancount ... для некоторых баз данных. К сожалению, универсально это узнать нельзя.
Значит надо добавлять явный запрос на начало второй транзакции. И использовать как-то так:
AutoTransaction transaction(ourDatabase);
Код:
QSqlQuery query(ourDatabase);
if(! query.execute("insert ..." ) ) return;
transaction.commit();
transaction.begin();
if(! query.execute("update ... ") return;
Записан
Страниц: [1]   Вверх
  Печать  
 
Перейти в:  


Страница сгенерирована за 0.081 секунд. Запросов: 23.