Russian Qt Forum
Март 28, 2024, 15:02
Добро пожаловать,
Гость
. Пожалуйста,
войдите
или
зарегистрируйтесь
.
Вам не пришло
письмо с кодом активации?
1 час
1 день
1 неделя
1 месяц
Навсегда
Войти
Начало
Форум
WIKI (Вики)
FAQ
Помощь
Поиск
Войти
Регистрация
Russian Qt Forum
>
Forum
>
Qt
>
Базы данных
>
Работа с БД в отдельном потоке
Страниц: [
1
]
Вниз
« предыдущая тема
следующая тема »
Печать
Автор
Тема: Работа с БД в отдельном потоке (Прочитано 8105 раз)
INZER
Новичок
Offline
Сообщений: 20
Работа с БД в отдельном потоке
«
:
Май 30, 2022, 16:50 »
Решил вынести работу с базой данных в отдельный поток
Приложение строится на архитектуре Model-View-Presenter
В модели БД воркер (SqlWorker ниже), агрегирующий класс-исполнитель запросов (SqlQueryExecutor)
Код:
class SqlWorker : public QObject
{
Q_OBJECT
public:
explicit SqlWorker(QObject *parent = nullptr);
~SqlWorker ();
void addDbServer (QString serverName, QHostAddress address);
QList <QString> getDbServers ();
QString getLastUsedDbName () { return currentDbName; }
bool openDbConnection(QString serverName, QString login, QString password);
private:
QString currentDbName;
QHash<QString, QHostAddress> dbServers;
QThread * executorThread;
SqlQueryExecutor * executor;
signals:
void stopExecutor ();
void executorOpenDbConnection (QString, QString, QString, QString);
void dbErrorOccured (STATE, QString, QString, bool);
private slots:
void slotHandleDbError (qint8 error, QString errorDescription, QString dbName);
void slotDbConnected (QString);
};
class SqlQueryExecutor : public QObject
{
Q_OBJECT
public:
explicit SqlQueryExecutor(QObject *parent = nullptr);
~SqlQueryExecutor ();
private:
const QString strQueryA618;
QString strWhereA618;
A618SqlModel * model618;
void changeModel618 (const QString& query);
signals:
void dbConnected (QString);
void dbDbErrorAppears (qint8 error, QString errorDescription, QString dbName);
void return618Data (A618SqlModel & model);
void finished ();
public slots:
void slotStartExecutorThread ();
void slotStopExecutorThread ();
void slotOpenDbConnection (QString adress, QString serverName, QString login, QString password);
void slotGet618Messages (unsigned int turplesLimit);
};
class A618SqlModel : public QSqlQueryModel
{
Q_OBJECT
public:
A618SqlModel(QObject *parent = 0);
QVariant data(const QModelIndex &index, int role) const;
};
Q_DECLARE_METATYPE(A618SqlModel)
Проблема в том что ранее в однопоточном исполнении результат выполнения запроса попадал в модель A618SqlModel, котрая успешно скармливалась QtableView
Однако сейчас я не могу передать результат выполения запроса, так как не могу использовать A618SqlModel для передачи в виде параметра сигнала (не могу зарегистрировать его как метатип, потому что конструктор копирования закрыт).
Подскажите пожалуйста как правильно в Qt правильно передать результат выполния запроса к БД из другого потока.
Код:
QObject::connect(modelObject, SIGNAL(return618Data(A618SqlModel &)), this, SLOT(slotSet618Messages(A618SqlModel &)));
Код:
qRegisterMetaType<A618SqlModel>();
Заранее спасибо
Записан
sergek
Гипер активный житель
Offline
Сообщений: 861
Мы должны приносить пользу людям.
Re: Работа с БД в отдельном потоке
«
Ответ #1 :
Май 30, 2022, 17:18 »
Может, сделать наоборот - в вокер передать ссылку на TableView? Проблем с совместным использованием, вроде, не наблюдается.
Записан
Qt 5.13.0 Qt Creator 5.0.1
Win10, Ubuntu 20.04
INZER
Новичок
Offline
Сообщений: 20
Re: Работа с БД в отдельном потоке
«
Ответ #2 :
Май 30, 2022, 21:47 »
Спасибо, завтра обязательно попробую,
Была такая мысль, но сомневался в корректности доступа к табличке из другого потока.
Единственное что смущает - не нашел что у QTableView реализован конструктор копирования, как я понимаю без него не получится зарегистрироовать мета тип и, соответственно, установить коннекты между методами объектов.
Записан
sergek
Гипер активный житель
Offline
Сообщений: 861
Мы должны приносить пользу людям.
Re: Работа с БД в отдельном потоке
«
Ответ #3 :
Май 30, 2022, 22:00 »
Вы не поняли - я предлагаю использовать TableView из того потока, где вы работаете с базой. Т.е. в конструкторе вокера предусматриваете ссылку на вьюшник, ну и в конструкторе делаете tableView-> setModel(model618).
Записан
Qt 5.13.0 Qt Creator 5.0.1
Win10, Ubuntu 20.04
INZER
Новичок
Offline
Сообщений: 20
Re: Работа с БД в отдельном потоке
«
Ответ #4 :
Май 31, 2022, 07:11 »
Дело в том что у меня ~20 вью в которые необходимо отдавать результаты запросов. Не хочется хранить ссылки на вью в модели. Согласно архитектуре Model View Presenter отображение и модель не должны быть связаны друг с другом никак. Потому хочется прокидывать результат. Ну либо ссылку на требуемую вью непосредственно при запросе.
Записан
sergek
Гипер активный житель
Offline
Сообщений: 861
Мы должны приносить пользу людям.
Re: Работа с БД в отдельном потоке
«
Ответ #5 :
Май 31, 2022, 09:09 »
Да хоть 40, какая разница? Массив указателей, в отдельном методе установка модели. Не понимаю проблемы. Но хозяин - барин...
Записан
Qt 5.13.0 Qt Creator 5.0.1
Win10, Ubuntu 20.04
INZER
Новичок
Offline
Сообщений: 20
Re: Работа с БД в отдельном потоке
«
Ответ #6 :
Май 31, 2022, 09:16 »
Ни в коем случае не ругаюсь на ваше предложение, огромное спасибо за подсказку, не думал о таком решении, так как мыслил в связи с выбранной архитектурой. Реализую как временное решение.
Может кто то еще подскажет решения как из потока получить данные из БД.
Записан
sergek
Гипер активный житель
Offline
Сообщений: 861
Мы должны приносить пользу людям.
Re: Работа с БД в отдельном потоке
«
Ответ #7 :
Май 31, 2022, 09:45 »
Цитата: INZER от Май 31, 2022, 09:16
так как мыслил в связи с выбранной архитектурой.
Архитектура тут не виновата
Цитата: INZER от Май 31, 2022, 09:16
Может кто то еще подскажет решения как из потока получить данные из БД.
Еще как подскажут, жалеть будете, что спросили
Записан
Qt 5.13.0 Qt Creator 5.0.1
Win10, Ubuntu 20.04
INZER
Новичок
Offline
Сообщений: 20
Re: Работа с БД в отдельном потоке
«
Ответ #8 :
Июнь 01, 2022, 16:02 »
Если кому то вдруг пригодится через СИГНАЛ-СЛОТ можно прокидвать указатели на любые типы данных
Прокидываю указатель на QSqlQuery
Тему можно считать закрытой
Записан
sergek
Гипер активный житель
Offline
Сообщений: 861
Мы должны приносить пользу людям.
Re: Работа с БД в отдельном потоке
«
Ответ #9 :
Июнь 01, 2022, 22:11 »
Не очень понятно, что вы сделали, но имейте в виду, что подключение к БД может быть использовано только в том потоке, в котором оно было создано.
Записан
Qt 5.13.0 Qt Creator 5.0.1
Win10, Ubuntu 20.04
INZER
Новичок
Offline
Сообщений: 20
Re: Работа с БД в отдельном потоке
«
Ответ #10 :
Июнь 01, 2022, 23:20 »
Да, спасибо я знаю
Результат возвращаю во вью через указатель на QSqlQuery
Код:
void SqlQueryExecutor::slotGet618Data(uint turplesCount)
{
if (!QSqlDatabase::database().isOpen())
{
emit dbDbErrorAppears(QSqlError::ConnectionError, tr("Ошибка подключения к БД."), "");
return;
}
QSqlQuery * query618 = new QSqlQuery ();
QString sty;
if (turplesCount == 0)
sty = QString ("%1 %2 ORDER BY id DESC ").arg(strQueryA618, strWhereA618);
else
sty = QString ("%1 %2 ORDER BY id DESC %3 %4").arg(strQueryA618, strWhereA618, "LIMIT").arg(turplesCount);
query618->exec(sty);
if (query618->lastError().isValid())
{
emit dbDbErrorAppears(query618->lastError().type(), query618->lastError().text(), "");
return;
}
emit set618Data(query618);
}
Записан
sergek
Гипер активный житель
Offline
Сообщений: 861
Мы должны приносить пользу людям.
Re: Работа с БД в отдельном потоке
«
Ответ #11 :
Июнь 02, 2022, 08:31 »
Как я понял, модель у вас в гуёвом потоке? Так делать нельзя по той причине, о которой я вам напоминал.
Другой вопрос, можно ли перенести модель в поток БД и использовать ее для нескольких представлений, существующих в основном потоке? Не уверен, может, коллеги что подскажут?
Upd. Да, собственно, и не нужны подсказки. Тут простая логика - модель должна быть одна, связана с источником данных (БД) и находиться в потоке БД. Представлений может быть много и находиться они в любом потоке. Так что см. мой первый совет.
«
Последнее редактирование: Июнь 02, 2022, 14:27 от sergek
»
Записан
Qt 5.13.0 Qt Creator 5.0.1
Win10, Ubuntu 20.04
diten
Новичок
Offline
Сообщений: 1
Re: Работа с БД в отдельном потоке
«
Ответ #12 :
Июнь 21, 2022, 08:20 »
Нужно в том потоке создавать динамически экземпляр модели.
В методе инициализации окна:
connect(ссылка_на_объект_класса_потока_работающего_с_БД, SIGNAL(resultReady(QSqlQueryModel*)), this, SLOT(completeModel(QSqlQueryModel*)));
В определение класса, который работает с БД:
QSqlQueryModel *model;
В методе run():
model = new QSqlQueryModel();
model->setQuery(qry, db);
emit resultReady(this->model);
Это решение вашей проблемы. Но, есть в этом подводный камень, иногда выносит ошибку во время присвоения модели в QTableView. Пока в поисках, как это сделать правильно
Записан
Страниц: [
1
]
Вверх
Печать
« предыдущая тема
следующая тема »
Перейти в:
Пожалуйста, выберите назначение:
-----------------------------
Qt
-----------------------------
=> Вопросы новичков
=> Уроки и статьи
=> Установка, сборка, отладка, тестирование
=> Общие вопросы
=> Пользовательский интерфейс (GUI)
=> Qt Quick
=> Model-View (MV)
=> Базы данных
=> Работа с сетью
=> Многопоточное программирование, процессы
=> Мультимедиа
=> 2D и 3D графика
=> OpenGL
=> Печать
=> Интернационализация, локализация
=> QSS
=> XML
=> Qt Script, QtWebKit
=> ActiveX
=> Qt Embedded
=> Дополнительные компоненты
=> Кладовая готовых решений
=> Вклад сообщества в Qt
=> Qt-инструментарий
-----------------------------
Программирование
-----------------------------
=> Общий
=> С/C++
=> Python
=> Алгоритмы
=> Базы данных
=> Разработка игр
-----------------------------
Компиляторы и платформы
-----------------------------
=> Linux
=> Windows
=> Mac OS X
=> Компиляторы
===> Visual C++
-----------------------------
Разное
-----------------------------
=> Новости
===> Новости Qt сообщества
===> Новости IT сферы
=> Говорилка
=> Юмор
=> Объявления
Загружается...