2017-10-28 74 views
1

因此,即时消息有关于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(); 
} 

作为一种尝试,以减轻这个问题,我宣布在第二类的新数据库变量,这没有奏效。 任何帮助,将不胜感激!

+0

你说你不关闭数据库,但你在析构函数中做这件事。没有必要在代码的每个部分打开数据库,只需在main.cpp中执行它,QSqlDatabase有一个全局实例。你叫什么摧毁? – eyllanesc

+0

尽管析构函数,我仍然收到错误,谢谢你的评论,但我会尝试在主要开放! – Renierler

回答

0

首先,你必须了解QSqlDatabase是如何工作的。

Qt管理数据库连接列表。每个连接都由一个唯一的名称标识。您可以添加新连接,检索现有连接或从列表中删除连接。这是使用函数完成:

  • QSqlDatabase::addDatabase()
  • QSqlDatabase::database()
  • QSqlDatabase::removeDatabase()

同样的QSqlDatabase几个实例可以参考相同的连接。因此,在以下代码db0db1中引用相同的连接。

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(); 
} 
+0

非常感谢您的好评! @Benjamin T – Renierler

0

每次调用addDatabase同一基础数据库的时候,请确保您设置一个唯一的连接名称:

if (QSqlDatabase::contains("foo")) { 
    QSqlDatabase::removeDatabase("foo"); 
} 
db = QSqlDatabase::addDatabase("QMYSQL", "foo"); 
db.setDatabaseName("securitydb"); 

注意,连接名字不一样的数据库名。所以在这里你打开多个独立的连接到同一个数据库。

如果您没有明确设置连接名称,Qt将使用默认值。此默认连接名称将用于对基础数据库的所有访问。因此,如果您在以默认连接名称打开的数据库上调用close(),则它将有效关闭使用该默认名称打开的所有数据库对象的