Qt在不在主类中的函数中执行SQL命令
因此,即时消息有关于qt和sql命令的一个问题,我已经坐了几个小时,但更容易发生,而不是简单。Qt在不在主类中的函数中执行SQL命令
我试图有多种形式,在每一个我连接数据库,并执行一些操作。这工作正常,但是 - 只要我将所述操作移动到说按钮按下功能,我收到数据库未打开错误。我不关闭这个类中的任何地方的数据库,但错误仍然存在。
我已经看到了问题的一部分是以下错误:
QSqlDatabasePrivate :: removeDatabase:连接“qt_sql_default_connection”仍然在使用,所有的查询将停止工作。
QSqlDatabasePrivate :: addDatabase:重复的连接名称'qt_sql_default_connection',旧的连接被删除。
当我重新构造代码(用于调试)并删除第一种形式的连接时,错误消失,并且数据库在第二类函数中保持打开状态。 下面,次级类
HomeScreen::HomeScreen(QWidget *parent):QWidget(parent),ui(newUi::HomeScreen){
ui->setupUi(this);
connect(ui->btnInclogShow,SIGNAL(pressed()),this,SLOT(ShowLogs()));
dbe = QSqlDatabase::addDatabase("QMYSQL");
dbe.setDatabaseName("securitydb");
dbe.setUserName("root");
dbe.setPassword("");
dbe.open();
if(dbe.open()){
qDebug() << "Database is open in main part";
}
else{qDebug() << "Database is closed";}
}
HomeScreen::~HomeScreen()
{
delete ui;
}
void HomeScreen::ShowLogs()
{
qDebug() << "Showlogs pressed";
if(dbe.open()){
qDebug() << "Database is open";
}
else{qDebug() << "Database is closed";}
}
下面初级班
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
db = QSqlDatabase::addDatabase("QMYSQL");
db.setDatabaseName("securitydb");
db.setUserName("root");
db.setPassword("");
db.open();
connect(ui->btnLogin,SIGNAL(pressed()),this,SLOT(LoginClicked()));
if(db.open()){
qDebug() << "Database is open";
}
else{qDebug() << "Database is closed";}
}
MainWindow::~MainWindow()
{
delete ui;
db.close();
db.removeDatabase("securitydb");
}
void MainWindow::LoginClicked()
{
qDebug() << "pressed";
this->destroy();
HomeScreengui->show();
}
作为一种尝试,以减轻这个问题,我宣布在第二类的新数据库变量,这没有奏效。 任何帮助,将不胜感激!
首先,你必须了解QSqlDatabase
是如何工作的。
Qt管理数据库连接列表。每个连接都由一个唯一的名称标识。您可以添加新连接,检索现有连接或从列表中删除连接。这是使用函数完成:
QSqlDatabase::addDatabase()
QSqlDatabase::database()
QSqlDatabase::removeDatabase()
同样的QSqlDatabase
几个实例可以参考相同的连接。因此,在以下代码db0
和db1
中引用相同的连接。
QSqlDatabase db0 = QSqlDatabase::addDatabase("MYSQL", "foo");
QSqlDatabase db1 = QSqlDatabase::database("foo");
此外,在需要连接名称的函数中,可以省略名称。 Qt会将其作为默认数据库处理。如果只有一个连接,这可能很方便。
请注意,Qt使用“qt_sql_default_connection”作为默认数据库的名称。因此,例如QSqlDatabase::database()
和QSqlDatabase::database("qt_sql_default_connection")
返回相同的连接。
现在看看你的代码。您可以在两个构造函数中调用QSqlDatabase::addDatabase("QMYSQL");
。第二个调用将在由Qt管理的连接列表中添加一个新连接,并删除以前的连接。这就是为什么你有以下警告:
QSqlDatabasePrivate :: addDatabase:重复的连接名 'qt_sql_default_connection',旧的连接删除。
而且因为拆除连接在使用,你会得到一个额外的警告:
QSqlDatabasePrivate :: removeDatabase:连接 “qt_sql_default_connection”仍然在使用,所有的查询将不再 工作。
要解决此问题,您只需拨打QSqlDatabase::addDatabase()
一次。这可以通过让你的一个类负责处理数据库连接来完成,其他类只会调用QSqlDatabase::database()
,但是你必须确保你只有这个类的一个实例。或者你可以在每一个类拨打电话到QSqlDatabase::addDatabase()
,但只有当数据库中不存在(见QSqlDatabase::contains()):
// Add a default databse only if it does not exist.
if (!QSqlDatabase::contains())
{
QSqlDatabase::addDatabase("MYSQL");
}
而且你行db.removeDatabase("securitydb");
是完全错误的。 QSqlDatabase::removeDatabase()
是一个静态函数,参数是连接名称,而不是数据库名称。它应该是:
QSqlDatabase::removeDatabase(); // Remove the default database
所以,你的代码应该是这样的:
HomeScreen::HomeScreen(QWidget *parent):QWidget(parent),ui(newUi::HomeScreen)
{
ui->setupUi(this);
connect(ui->btnInclogShow, &QPushButton::pressed, this, &HomeScreen::ShowLogs);
if (QSqlDatabase::contains())
dbe = QSqlDatabase::addDatabase("QMYSQL");
else
dbe = QSqlDatabase::database();
dbe.setDatabaseName("securitydb");
dbe.setUserName("root");
dbe.setPassword("");
if(dbe.open()){
qDebug() << "Database is open in main part";
}
else{
qDebug() << dbe.lastError().text();
}
}
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
if (QSqlDatabase::contains())
db = QSqlDatabase::addDatabase("QMYSQL");
else
db = QSqlDatabase::database();
db.setDatabaseName("securitydb");
db.setUserName("root");
db.setPassword("");
connect(ui->btnLogin, &QPushButton::pressed,this, &MainWindow::LoginClicked);
if(db.open()){
qDebug() << "Database is open";
}
else{
qDebug() << dbe.lastError().text();
}
}
MainWindow::~MainWindow()
{
delete ui;
// WARNING: If HomeScreen is still using the connection the next 2 lines will leak resources and make HomeScreen lose its connection.
db.close();
QSqlDatabase::removeDatabase();
}
非常感谢您的好评! @Benjamin T – Renierler
每次调用addDatabase
同一基础数据库的时候,请确保您设置一个唯一的连接名称:
if (QSqlDatabase::contains("foo")) {
QSqlDatabase::removeDatabase("foo");
}
db = QSqlDatabase::addDatabase("QMYSQL", "foo");
db.setDatabaseName("securitydb");
注意,连接名字不一样的数据库名。所以在这里你打开多个独立的连接到同一个数据库。
如果您没有明确设置连接名称,Qt将使用默认值。此默认连接名称将用于对基础数据库的所有访问。因此,如果您在以默认连接名称打开的数据库上调用close()
,则它将有效关闭使用该默认名称打开的所有数据库对象的。
你说你不关闭数据库,但你在析构函数中做这件事。没有必要在代码的每个部分打开数据库,只需在main.cpp中执行它,QSqlDatabase有一个全局实例。你叫什么摧毁? – eyllanesc
尽管析构函数,我仍然收到错误,谢谢你的评论,但我会尝试在主要开放! – Renierler