首页 > 解决方案 > QSqlDatabase:如何避免“qt_sql_default_connection”仍在使用和重复连接相关警告?

问题描述

抱歉,如果这是一个微不足道的问题,但我一直在尝试构建一个小的 .ui 用作QSQLITE数据库,并用于QTableView在默认数据库文件上显示 4 列作为示例。

我在各个方面都调试了问题,更改了逻辑操作SQL并以更简单的方式重组了构造函数,但错误仍然存​​在。

完成设置所有参数后,我收到此错误:

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.

我查看了描述此错误的几个来源,例如此来源、此其他来源。这很有用,但仍然没有任何反应。官方文档在这里提出了一种“错误”和“正确”的方法。但错误仍然存​​在。在所有这些不同的选项之后,我以更简洁的方式恢复了代码,我希望有人可以阐明这个问题。

下面的代码片段:

主窗口.h

private:
    QString temporaryFolder;
    dataInfo *mNewDatabaseImages;
    QSqlTableModel *mNewTableImages;

主窗口.cpp

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    temporaryFolder = "/home/to/Desktop/tempDBFolder/tmp.db";
    QFile dbRem(temporaryFolder);
    dbRem.remove();
    mNewDatabaseImages = new dataInfo(this);
    mNewDatabaseImages->initDataBase(temporaryFolder);
    mNewDatabaseImages->confDataBase();
    mNewTableImages = new QSqlTableModel(this, mNewDatabaseImages->getDatabase());
    mNewTableImages->setTable("leftCamTable");
    mNewTableImages->select();
    ui->bookMarkTableView->setModel(mNewTableImages);
    ui->bookMarkTableView->showColumn(true);
}

数据信息.h

#ifndef DATAINFO_H
#define DATAINFO_H
#include <QObject>
#include <QSqlDatabase>
#include "imageparam.h"

class dataInfo : public QObject
{
    Q_OBJECT
public:
    explicit dataInfo(QObject *parent = nullptr);
    bool initDataBase(const QString &nameDB);
    bool confDataBase();
    bool addItem(ImageParam* imageItem);
    QSqlDatabase getDatabase();
private:
    QString mError;
    QSqlDatabase mDBImages;
};
#endif // DATAINFO_H

数据信息.cpp

#include "datainfo.h"
#include <QSqlQuery>
#include <QSqlError>
#include <QDebug>
#include <QVariant>
#include <QMessageBox>

#define CREATE_TABLE \
    " CREATE TABLE IF NOT EXISTS imageTable" \
    " (id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL" \
    " path1 TEXT NOT NULL" \
    " path2 TEXT NOT NULL" \
    " imageA BLOB NOT NULL" \
    " imageB BLOB NOT NULL)"

dataInfo::dataInfo(QObject *parent) : QObject(parent)
{}

bool dataInfo::initDataBase(const QString &nameDB)
{
    mDBImages = QSqlDatabase::addDatabase("QSQLITE");
    mDBImages.setDatabaseName(nameDB);
    bool ok = mDBImages.open();
    if(!ok) {
        mError = mDBImages.lastError().text();
        qDebug() << mError;
    }
    return ok;
}

bool dataInfo::confDataBase()
{
    QSqlQuery qry;
    bool ok = qry.exec(CREATE_TABLE);
    if(!ok) {
        mError = qry.lastError().text();
    }
    return ok;
}

bool dataInfo::addItem(ImageParam *imageItem)
{
    QSqlQuery qry;
    qry.prepare("INSERT INTO imageTable (path1, path2, imageA, imageB)" \
                " VALUES (?,?,?,?)");
    qry.addBindValue(imageItem->path1());
    qry.addBindValue(imageItem->path2());
    qry.addBindValue(imageItem->image1());
    qry.addBindValue(imageItem->image2());
    bool ok = qry.exec();
    if(!ok) {
        mError = qry.lastError().text();
    }
    return ok;
}

QSqlDatabase dataInfo::getDatabase()
{
    return mDBImages;
}

我还查看了这篇建议首先为数据库设置名称的帖子,但我已经在函数中这样做了initDataBase(const QString &nameDB)。这是建议该程序的帖子,如下所示:

db->setDatabaseName("name");
if(!db->open()) {
    qDebug() << "Error opening ";
    return false;
}

请阐明可能的解决方案。

标签: c++qtsqliteqt5qtableview

解决方案


简短的回答

  • 您应该指定要在其上运行的数据库QSqlQuery,否则它们将在默认数据库上运行。QSqlQuery您可以在的构造函数中指定数据库

    QSqlQuery query(QSqlDatabase::database("my-db"));

  • QSqlDatabase作为班级成员保留了 的副本dataInfo,这将阻止它正确关闭。相反,只需QSqlDatabase::database("name")在需要时使用静态。

    auto db = QSqlDatabase::database("my-db");

细节

为 QSqlQuery 提供正确的数据库

更改您对QSqlQuery. 例如confDataBase

bool dataInfo::confDataBase()
{
    // Explicitly provide your database to the query
    // Otherwise the default database is used
    QSqlQuery qry(getDatabase());
    bool ok = qry.exec(CREATE_TABLE);
    if(!ok) {
        mError = qry.lastError().text();
    }
    return ok;
}

不保留 QSqlDatabase 属性

从文档中:

警告:强烈建议您不要将 QSqlDatabase 的副本作为类的成员保留,因为这将阻止实例在关闭时被正确清理。如果您需要访问现有的 QSqlDatabase,则应使用 database() 访问它。如果你选择有一个 QSqlDatabase 成员变量,则需要在删除 QCoreApplication 实例之前将其删除,否则可能会导致未定义的行为。

将您的数据库名称存储在您的类中,并将您的更改getDatabase

数据信息.cpp

bool dataInfo::initDataBase(const QString &nameDB)
{
    // Save database's name
    mDBName = nameDB;
    // Use the database locally, without storing it
    auto dbImages = QSqlDatabase::addDatabase("QSQLITE", nameDB);
    bool ok = dbImages.open();
    if(!ok) {
        mError = dbImages.lastError().text();
        qDebug() << mError;
    }
    return ok;
}

QSqlDatabase dataInfo::getDatabase()
{
    return QSqlDatabase::database(mDBName);
}

数据信息.h

private:
    QString mError;
    QString mDBName;

Qt 的代码生成警告

查看产生错误的实际代码:https ://code.woboq.org/qt5/qtbase/src/sql/kernel/qsqldatabase.cpp.html#170

invalidateDb在添加或删除连接时使用,如果引用计数> 1,将触发错误。当您持有一个时,这将触发错误。


推荐阅读