QT QSqlDatabase может быть создан только один раз

113
08 января 2021, 11:40

Есть класс:

class DataBase
{
protected:
bool DataBase::connectToDB()
{
    db.setHostName(DBHOSTNAME);
    db.setDatabaseName(DBNAME);
    db.setUserName(DBUSERNAME);
    db.setPassword(DBPASSWORD);
    return db.open();
}
    QSqlQuery query;
private:
    QSqlDatabase db = QSqlDatabase::addDatabase("QMYSQL3");
    const QString DBHOSTNAME = "****",
            DBUSERNAME = "****",
            DBPASSWORD = "****",
            DBNAME = "****";
};

И

class DataBaseManager: public DataBase
{
public:
    QVector<QVariant> getItem(const QString name);
    QVector<QVariant> getItem(const QString name, const QString where, const QString whereData);
// другие функции
};

В классе стартового окна

DataBaseManager ManagerDB;

Но, нужно использовать DataBaseManager в нескольких формах. Но ловлю:

QSqlDatabasePrivate::removeDatabase: connection 'qt_sql_default_connection' is still in use, all queries will cease to work.


QSqlDatabasePrivate::addDatabase: duplicate connection name 'qt_sql_default_connection', old connection removed.

Понимаю, что нужно использовать QSqlDatabase db = QSqlDatabase::addDatabase("QMYSQL3"); только один раз в программе, но не понимаю как реализовать

Answer 1

Вероятно, вам поможет применение singleton паттерна

static DataBaseManager& getInstance() {
    static DataBaseManager  instance;
    return instance;
}   

Будьте осторожны с применением данного паттерна с библиотекой Qt! Наследник QObject, хранимый статично, должен получать nullptr в качестве класса-владельца в параметрах конструктора: в противном случае есть рист получить Heap Corruption из-за штатной системы сборки мусора

Answer 2

Лучше в отдельной инициализирующей член-функции главного окна или специализированного класса один раз выполнить

//один раз создаёт соединение, которое можно получить в любой точке программы
QSqlDatabase db = QSqlDatabase::addDatabase("QMYSQL3"); 
db.setHostName(DBHOSTNAME);
db.setDatabaseName(DBNAME);
db.setUserName(DBUSERNAME);
db.setPassword(DBPASSWORD);
db.open();

и затем где надо использовать статическую функцию QSqlDatabase::database() для получения экземпляра ранее созданного соединения к БД, предварительно проверяя его на isValid().

Ошибка как раз и возникает, т.к. каждый раз при создании экземпляра DataBase снова вызывается статический метод QSqlDatabase::addDatabase("QMYSQL3");

QSqlDatabasePrivate::addDatabase: duplicate connection name 'qt_sql_default_connection', old connection removed.

А тут стоит обратить внимание на время жизни экземпляра QSqlDatabase, чтобы избежать утечек ресурсов.

QSqlDatabasePrivate::removeDatabase: connection 'qt_sql_default_connection' is still in use, all queries will cease to work.

READ ALSO
Как сделать проверку на валидацию перед сабмитом а после показать блок успешной отправки

Как сделать проверку на валидацию перед сабмитом а после показать блок успешной отправки

Надо сделать валидацию перед сабмитом, а после показать блок успешной отправки

102
Как создать массив объектов класса и обращаться к их методам? C# [дубликат]

Как создать массив объектов класса и обращаться к их методам? C# [дубликат]

Вопрос такой, есть у меня массив из объектов класса, например, MyClass:

121
C# MSSQL Что необходимо для запуска?

C# MSSQL Что необходимо для запуска?

Создал проект windows forms сNET v4

118