Another Database Question | MySQL



  • Hi All,

    I've setup a database handler class as follows.

    dbhandler.h

    @#ifndef DBHANDLER_H
    #define DBHANDLER_H
    #include <QList>
    #include <QtSql>

    class DbHandler
    {
    private:
    QSqlDatabase db;
    QList<QString> _currencyData;
    QList<QString> _lengthData;
    QList<float> _currencyRate;
    QList<float> _lengthRate;
    public:
    DbHandler();
    void readAllData();
    QList<QString> getCurrencyData();
    QList<float> getCurrencyRate();
    QList<QString> getLengthData();
    QList<float> getLengthRate();
    };

    #endif // DBHANDLER_H@

    dbhandler.cpp

    @#include "dbhandler.h"

    DbHandler::DbHandler() {
    db = QSqlDatabase::addDatabase("QMYSQL");
    db.setHostName("localhost");
    db.setDatabaseName("convertr");
    db.setUserName("root");
    db.setPassword("toor");
    readAllData(); // If it is called like this, it works fine
    }

    void DbHandler::readAllData() {
    if(db.open()) {
    qDebug() << "Opened database!";
    QSqlQuery qry;
    if(qry.exec("select * from currency;")) {
    while(qry.next()) {
    _currencyData.append(qry.value(0).toString());
    _currencyRate.append(qry.value(1).toFloat());
    }
    qDebug() << "Currency done!";
    }
    else {
    qDebug() << "Fetching currency data from db failed : " << db.lastError().text();
    }
    qry.finish();
    if(qry.exec("select * from length;")) {
    while(qry.next()) {
    _lengthData.append(qry.value(0).toString());
    _lengthRate.append(qry.value(1).toFloat());
    }
    qDebug() << "Length done!";
    }
    else {
    qDebug() << "Fetching length data from db failed";
    }
    qry.finish();
    db.close();
    } else {
    qDebug() << "Something went Wrong : " << db.lastError().text();
    }
    }

    QList<QString> DbHandler::getCurrencyData() {
    return _currencyData;
    }

    QList<float> DbHandler::getCurrencyRate() {
    return _currencyRate;
    }

    QList<QString> DbHandler::getLengthData() {
    return _lengthData;
    }

    QList<float> DbHandler::getLengthRate() {
    return _lengthRate;
    }
    @

    I've an object of this db handler class named _dbH. If I make a call to readAllData() with that object, the applicaion doesn't work. I get the following error.

    @Starting /home/napster/Programs/Learning-Qt/Convertr-build-desktop/Convertr...
    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.
    Something went Wrong : "Driver not loaded Driver not loaded"
    QSqlDatabasePrivate::removeDatabase: connection 'qt_sql_default_connection' is still in use, all queries will cease to work.
    /home/napster/Programs/Learning-Qt/Convertr-build-desktop/Convertr exited with code 0@

    But, if readAllData() is called from inside the constructor, it works fine.
    Can someone help me out? It may be some stupid misktake of mine, but remember I'm just another n00b! :)

    Thanks & Regards



  • This is normal behaviour, reported in the documentation. You should read QSqlDatabase Class Reference from the online help.

    Returning to the problem:
    -QSqlQuery qry; when you instance a qyerry like this the default database is used.
    -db = QSqlDatabase::addDatabase("QMYSQL"); If you don't provide as second argument a name for the database this becomes your default database.
    If you have one object as DbHandler everytime you call ReadAllData() Methor db.open will be called. In your case, when you have only a default database, db.open should be called only once. The second call of db.open will close previous connection an open a new one pointing to the same default database. In addition DBHandler should be singletone, or instanced only once. The second instance of DBHandler will throw you the same errors.

    In my opinion in constructor you should call db.open. and remove "if(db.open()) {" from ReadAllData.

    If you want to be sure that the database is open test that in constructor or make an automated variable in your readall method e.g.

    QSqlDatabase localTempDb = QSqlDatabase::database(); // This should return the default database object but in your code you don't need to have a QSqlDatabase object in that method so it's pointless. Open database only once in DBHandler constructor.

    I must repeat again this:D If you have a QSqlQuery object instanced without a name to a database the default database is used when you .exec() the querry.

    In case you must use more than one database you shuld take into consideration naming your databases connections. Again you musthave only one call of .open() for each database object.



  • Thank you bu7ch3r



  • Hope my last post made you thank me. Also I am very sorry about bad(very bad) spelling mistakes but sometimes when I am writing answers I am also debuging or writing code at work :D



  • A better place to open the database connection (and close it) would be at application startup. This way you make sure that nothing reopens an already open database handle and thus avoid invalidating open queries. The main() method or the constructor of your main window are good places for this.


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.