【问题标题】:QSqlDatabase: How to avoid 'qt_sql_default_connection' still in use & duplicate connection related warning?QSqlDatabase:如何避免“qt_sql_default_connection”仍在使用和重复连接相关警告?
【发布时间】:2019-08-07 13:23:49
【问题描述】:

对不起,如果这是一个微不足道的问题,但我一直在尝试构建一个小的 .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.

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

下面的代码片段:

ma​​inwindow.h

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

ma​​inwindow.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);
}

datainfo.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

datainfo.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;
}

我还查看了this post,它建议首先为数据库设置一个名称,但我已经在函数initDataBase(const QString &amp;nameDB) 中这样做了。这里是建议该过程的post,如下:

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

请说明可能的解决方案。

【问题讨论】:

    标签: c++ qt sqlite qt5 qtableview


    【解决方案1】:

    简答

    • 您应该指定要在其上运行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 更改为

    dataInfo.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);
    }
    

    dataInfo.h

    private:
        QString mError;
        QString mDBName;
    

    Qt 的代码生成警告

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

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

    【讨论】:

    • @Adrien Leravat,感谢您抽出宝贵时间阅读问题。我按照您的建议更改了 getDatabase() 函数,但它仍然无法正常工作。我认为您也指的是修改带有此语句mDBImages = QSqlDatabase::addDatabase("QSQLITE");initDataBase(const QString &amp;nameDB) 函数但是该函数应该如何修改?
    • 好的。我不认为更改 mDBImages = QSqlDatabase::addDatabase("QSQLITE"); 会有所帮助,只需使用本地实例就可以了。您能否尝试在addDatabase(...) 调用中直接传递数据库名称作为第二个参数?你在其他地方还有其他 QSqlDatabase 吗?我记得有这个问题,我不得不手动关闭每个数据库,并确保没有任何查询处于活动状态,但你警告中的 default 名称对我来说真的很奇怪。
    • 另外,如果您不将数据库提供给QSqlTableModel,问题会消失吗?如果您完全推荐您的QSqlTableModel 代码?您是否也摆脱了标题中的QSqlDatabase mDBImages;?这么多问题:)
    • 没问题 :) 感谢您的帮助!我现在正在尝试你的建议。给我几分钟验证一下。
    • 非常感谢您抽出时间 Adrien Leravat!
    猜你喜欢
    • 2023-04-10
    • 1970-01-01
    • 2016-11-17
    • 2018-09-03
    • 2014-08-31
    • 2019-12-18
    • 2019-02-21
    • 1970-01-01
    • 2016-12-25
    相关资源
    最近更新 更多