QSqlDatabase:如何避免'qt_sql_default_connection'仍然在使用和重复连接相关的警告?

问题描述 投票:1回答:1

很抱歉,如果这是一个微不足道的问题,但我一直在尝试构建一个小的.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 source,这个other sourcethis也很有用,但仍然没有任何反应。官方文件提出了一种“错误”和“正确”的方式来做here。但错误仍然存​​在。在所有这些不同的选项之后,我以更简洁的方式带回了代码,我希望有人可以解释这个问题。

在代码片段下方:

mainwindow.h

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

mainwindow.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 &nameDB)中做了。这里提出了程序的post,如下:

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

请详细说明可能的解决方案。

c++ qt sqlite qt5 qtableview
1个回答
3
投票

简短的回答

  • 您应该指定要运行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,将触发错误。当您持有一个时,这将触发错误。

© www.soinside.com 2019 - 2024. All rights reserved.