Richtiger Umgang mit QSqlDatabase
-
Morgen, Danke @jsulm für die Ausführliche Erklärung. Ich werde es mir heute Abend nach der Arbeit nochmal genauer ansehen. Was ich noch nicht ganz verstanden habe ist.
Alternativ deklariert man die sqldb Variable als static, dann wird diese nur einmal initialisiert.
Auf die schnelle wollte ich einfach mal Testen,
static QSqlDatabase sqldb = QSqlDatabase::addDatabase("QMYSQL");
Das nahm mein Kompiler aber erst gar nicht an.
Eigentlich is die sqlc Variable in MySqlConnect nicht notwendig, da ja QSqlDatabase diese ja schon vorhält.
Im Beispiel habe ich in MySqlConnect die Variable sqlc gar nicht verwendet, nur im Forum. Und dort Initialisiere ich sozusagen die Klasse damit ich auf deren Funktionen zugreifen kann. Ist das falsch?
Wenn ja, kann mir jemand ein Beispiel geben wie das richtig eingesetzt wird.
Danke!
Gruß knasan
// Im header static QSqlDatabase sqldb; //in cpp QSqlDatabase MySqlConnect::sqldb = QSqlDatabase::addDatabase("QMYSQL");
"Im Beispiel habe ich in MySqlConnect die Variable sqlc gar nicht verwendet" - spielt ja keine Rolle, da sqldb immer initialisiert wird unabhängig davon ob es benutzt wird oder nicht.
-
Also, so wirklich will das bei mir noch nicht.
Im Header habe ich QSqlDatabase als static deklariert.mysqlconnect.h
private: static QSqlDatabase sqldb;
In mysqlconnect.cpp
Habe ich ein addDatabase versucht.
QSqlDatabase MySqlConnect::sqldb = QSqlDatabase::addDatabase("QMYSQL");
Dann bekommich ich die Fehlermeldung:
qualified-id declaration before = token.und wenn einfach nur
QSqlDatabase sqldb = QSqlDatabase::addDatabase("QMYSQL");
Mache, was für mich auf den ersten Blick auch logisch erscheint, da ich ja die Variable sqldb deklariert habe, bekomme ich in jeder Funktion innerhalb von MySQLConnect die Fehlermeldung:
undefinied reference to MySqlConnect::sqldb
oder muss ich die Datenbank nicht in mysqlconnect.cpp machen sondern, wie in diesem Beispiel in Forum.cpp ?
Das verstehe ich noch nicht so ganz.
-
Also, so wirklich will das bei mir noch nicht.
Im Header habe ich QSqlDatabase als static deklariert.mysqlconnect.h
private: static QSqlDatabase sqldb;
In mysqlconnect.cpp
Habe ich ein addDatabase versucht.
QSqlDatabase MySqlConnect::sqldb = QSqlDatabase::addDatabase("QMYSQL");
Dann bekommich ich die Fehlermeldung:
qualified-id declaration before = token.und wenn einfach nur
QSqlDatabase sqldb = QSqlDatabase::addDatabase("QMYSQL");
Mache, was für mich auf den ersten Blick auch logisch erscheint, da ich ja die Variable sqldb deklariert habe, bekomme ich in jeder Funktion innerhalb von MySQLConnect die Fehlermeldung:
undefinied reference to MySqlConnect::sqldb
oder muss ich die Datenbank nicht in mysqlconnect.cpp machen sondern, wie in diesem Beispiel in Forum.cpp ?
Das verstehe ich noch nicht so ganz.
@knasan said in Richtiger Umgang mit QSqlDatabase:
Habe ich ein addDatabase versucht.
QSqlDatabase MySqlConnect::sqldb = QSqlDatabase::addDatabase("QMYSQL");Wo? Es muss in MySqlConnect.cpp passieren.
QSqlDatabase sqldb = QSqlDatabase::addDatabase("QMYSQL");
das definiert eine neue sqldb Variable die überhaupt nichts mit MySqlConnect zu tun hat.
"was für mich auf den ersten Blick auch logisch erscheint, da ich ja die Variable sqldb deklariert habe" - deklariert wurde diese als Member-Variable in MySqlConnect, in der Zeile oben wird aber eine neue Variable mit dem gleichen namen definiert. -
Ich habe es im constructor in mysqlconnect.cpp eingetragen und die oben genannten Fehlermeldung bekommen.
mysqlconnect.h
private: static QSqlDatabase sqldb;
mysqlconnect.cpp
MySqlConnect::MySqlConnect(QObject *parent) : QObject(parent) { QSqlDatabase MySqlConnect::sqldb = QSqlDatabase::addDatabase("QMYSQL"); sqldb.setHostName("localhost"); sqldb.setPassword("1b7cq"); sqldb.setUserName("forum"); sqldb.setDatabaseName("forumsqldatabase"); }
Dann erhalte ich die Fehlermeldung:
mysqlconnect.cpp:12: Fehler: qualified-id in declaration before ‘=’ token QSqlDatabase MySqlConnect::sqldb = QSqlDatabase::addDatabase("QMYSQL"); ^
Gruß Knasan
-
Ich habe es im constructor in mysqlconnect.cpp eingetragen und die oben genannten Fehlermeldung bekommen.
mysqlconnect.h
private: static QSqlDatabase sqldb;
mysqlconnect.cpp
MySqlConnect::MySqlConnect(QObject *parent) : QObject(parent) { QSqlDatabase MySqlConnect::sqldb = QSqlDatabase::addDatabase("QMYSQL"); sqldb.setHostName("localhost"); sqldb.setPassword("1b7cq"); sqldb.setUserName("forum"); sqldb.setDatabaseName("forumsqldatabase"); }
Dann erhalte ich die Fehlermeldung:
mysqlconnect.cpp:12: Fehler: qualified-id in declaration before ‘=’ token QSqlDatabase MySqlConnect::sqldb = QSqlDatabase::addDatabase("QMYSQL"); ^
Gruß Knasan
@knasan Das gehört NICHT in den Konstruktor! Statische variablen werden in C++ nur einmal initialisiert.
Siehe: https://www.tutorialspoint.com/cplusplus/cpp_static_members.htm -
Hallo @jsulm, danke für diesen Hinweis. Hab noch viel zu Lernen ;-)
Ich muss mir das Beispiel vom Link mal durchspielen und damit etwas rumspielen um das ganze komplett zu verstehen.
Ich habe jetzt eine neu Funktion OpenDBSQL(); hinzugefügt als privat. Aber auch hier erhalte ich die gleiche Fehlermeldung:
mysqlconnect.cpp:15: Fehler: qualified-id in declaration before ‘=’ token QSqlDatabase MySqlConnect::sqldb = QSqlDatabase::addDatabase("QMYSQL"); ^
Gruß Knasan
-
Hallo @jsulm, danke für diesen Hinweis. Hab noch viel zu Lernen ;-)
Ich muss mir das Beispiel vom Link mal durchspielen und damit etwas rumspielen um das ganze komplett zu verstehen.
Ich habe jetzt eine neu Funktion OpenDBSQL(); hinzugefügt als privat. Aber auch hier erhalte ich die gleiche Fehlermeldung:
mysqlconnect.cpp:15: Fehler: qualified-id in declaration before ‘=’ token QSqlDatabase MySqlConnect::sqldb = QSqlDatabase::addDatabase("QMYSQL"); ^
Gruß Knasan
@knasan Noch mal: wenn sqldb static ist dann gehört diese Zeile in KEINE Methode/Konstruktor, sondern einfach in eine cpp Datei:
QSqlDatabase MySqlConnect::sqldb = QSqlDatabase::addDatabase("QMYSQL"); MySqlConnect::MySqlConnect(QObject *parent) : QObject(parent) { sqldb.setHostName("localhost"); sqldb.setPassword("1b7cq"); sqldb.setUserName("forum"); sqldb.setDatabaseName("forumsqldatabase"); }
Das stellt sicher, dass statische Variablen nur ein Mal initialisiert werden. Das wird auch in dem Link von mir so gemacht.
-
Sorry wenn ich jetzt nochmal genauer Nachfrage. Meinst du, dies gehört nicht in mysqlconnect.cpp sondern in einer Datei die meine Klasse mysqlconnect verwendet? In meinem Beispiel also in forum.cpp?
Gruß knasan
-
Achso, es muss außerhalb einer Funktion stehen. Sozusagen global deklariert werden aber in mysqlconnect.cpp und da das Schlüsselwort static verwendet wurde wird diese nur einmal initialisiert.
-
@jsulm vielen lieben Dank für diese Erklärung. Hab viel Dazugelernt.
Ich habe es in mein Hauptprojekt getestet und Funktioniert auch soweit super.
Leider gibt es immer ein "aber" und so auch in meinem Fall.In meinem Hauptprojekt verwende ich zwei Datenbanken, eine QMYSQL und eine QSQLITE.
Sobald ich die QSQLITE auch als Static deklariere, funktioniert der Zugriff auf MySQL gar nicht mehr - "Driver not loaded". Es spielt hierbei keine Rolle ob ich die Klasse überhaupt verwende oder nicht. SQLite Funktioniert weiterhin.Ich wollte dieses Problem mit eigen definierte ConnectionName umgehen. Dann habe ich jedoch überhaupt gar keinen Zugriff auf die Datenbank mehr. (MySQL und SQLite)
QSqlDatabase MySqlConnect:sqldb = QSqlDatabase::addDatabase("QMYSQL","first");
Verwende ich keine expliziten ConnectionName oder "qt_sql_default_connection", funktioniert der Zugriff
QSqlDatabase MySqlConnect:sqldb = QSqlDatabase::addDatabase("QMYSQL","qt_sql_default_connection");
Gruß Knasan
-
@jsulm vielen lieben Dank für diese Erklärung. Hab viel Dazugelernt.
Ich habe es in mein Hauptprojekt getestet und Funktioniert auch soweit super.
Leider gibt es immer ein "aber" und so auch in meinem Fall.In meinem Hauptprojekt verwende ich zwei Datenbanken, eine QMYSQL und eine QSQLITE.
Sobald ich die QSQLITE auch als Static deklariere, funktioniert der Zugriff auf MySQL gar nicht mehr - "Driver not loaded". Es spielt hierbei keine Rolle ob ich die Klasse überhaupt verwende oder nicht. SQLite Funktioniert weiterhin.Ich wollte dieses Problem mit eigen definierte ConnectionName umgehen. Dann habe ich jedoch überhaupt gar keinen Zugriff auf die Datenbank mehr. (MySQL und SQLite)
QSqlDatabase MySqlConnect:sqldb = QSqlDatabase::addDatabase("QMYSQL","first");
Verwende ich keine expliziten ConnectionName oder "qt_sql_default_connection", funktioniert der Zugriff
QSqlDatabase MySqlConnect:sqldb = QSqlDatabase::addDatabase("QMYSQL","qt_sql_default_connection");
Gruß Knasan
@knasan said in Richtiger Umgang mit QSqlDatabase:
Driver not loaded
Das ist ein komplett anderes Problem. Sehr wahrscheinlich fehlt die MySQL Client Library.
Siehe z.B. hier was zu tun ist: https://stackoverflow.com/questions/40130698/qt-5-7-mysql-driver-not-loaded -
@jsulm said in Richtiger Umgang mit QSqlDatabase:
Das ist ein komplett anderes Problem. Sehr wahrscheinlich fehlt die MySQL Client Library.
Siehe z.B. hier was zu tun ist: https://stackoverflow.com/questions/40130698/qt-5-7-mysql-driver-not-loadedDie Verbindung geht ja, wenn ich nur QMYSQL Verwende. Nur Zusammen mit einer weiteren Datenbank QSQLITE klappt die Verbindung nicht mehr. Die Treiber für MySQL unter Linux und den Connector C++ für Windows habe ich auf meine Systeme drauf. Daran kann es also nicht liegen.
-
@jsulm said in Richtiger Umgang mit QSqlDatabase:
Das ist ein komplett anderes Problem. Sehr wahrscheinlich fehlt die MySQL Client Library.
Siehe z.B. hier was zu tun ist: https://stackoverflow.com/questions/40130698/qt-5-7-mysql-driver-not-loadedDie Verbindung geht ja, wenn ich nur QMYSQL Verwende. Nur Zusammen mit einer weiteren Datenbank QSQLITE klappt die Verbindung nicht mehr. Die Treiber für MySQL unter Linux und den Connector C++ für Windows habe ich auf meine Systeme drauf. Daran kann es also nicht liegen.
@knasan "Sobald ich die QSQLITE auch als Static deklariere" - als weiter statische Variable? So
QSqlDatabase MySqlConnect:sqldb1 = QSqlDatabase::addDatabase("QMYSQL", "first"); QSqlDatabase MySqlConnect:sqldb2 = QSqlDatabase::addDatabase("QSQLITE", "second");
?
Man kann ja nicht die gleiche sqldb Variable für mehr als eine Verbindung zur gleichen Zeit benutzen.
Ehrlich gesagt verstehe ich immer noch nicht varum diese Variable überhaupt benötigt wird? Man kann eine Verbindung jeder Zeit von QSqlDatabase über ihren Namen bekommen. Wozu also der ganze Aufwand? -
@jsulm ja so ähnlich.
Ich habe zwei Klassen eine für MySQL und eine für SQLite.
In den Header habe ich beide Datenbanken als Private und Static deklariert.qcsql.h
static QSqlDatabase dbMySQL;
und im Code qcsql.cpp
in keiner Funktion usw. also wieder global einQSqlDatabase QCSql::dbMySQL = QSqlDatabase::addDatabase("QMYSQL");
qcsqlite.h
static QSqlDatabase dbSQLite;
qcsqlite.cpp
QSqlDatabase QcSQLite::dbSQLite = QSqlDatabase::addDatabase("QSQLITE");
In mein Hauptcode greife ich über Klassen auf die jeweilige Funktionen zu.
Als erstes wird auf die SQLite zugegriffen, dort erscheint keine Fehlermeldung.
Wenn ich aber auf die MYSQL Funktionen zugreife, erhalte ich die Fehlermeldung "driver not loaded".
Diese Meldung kommt aber unabhängig ob ich auf die SQLite zugegriffen habe oder nicht, sobald SQLITE als static deklariert wurde, geht der Zugriff einfach auf MySQL nicht mehr.Wenn ich SQLITE nicht als static deklariere sondern den Treiber in den Header Initializiere, klappt der Zugriff auf der MySQL, allerdings darf man dann voher nicht SQLITE benutzt haben. Sobald ich SQLITE verwende geht der Zugriff auf der MySQL nicht mehr mit der Fehlermeldung "driver not loaded".
Im Hauptprogramm cpp
In einer Funktion ....QcSQLite qcsqlite; QStringList lastConnectInfoList = qcsqlite.GetLastConnectionsServer(); // Zugriff auf SQLite
In einer anderen Funktion Zugriff auf MySQL
QCSql qcsql; QSqlQuery query(qcsql.mysqlquery(myquery));
Wobei die SQLite beim ersten Aufruf automatisch aufgerufen wird und die der MySQL nur nach bedarf.
-
@jsulm ja so ähnlich.
Ich habe zwei Klassen eine für MySQL und eine für SQLite.
In den Header habe ich beide Datenbanken als Private und Static deklariert.qcsql.h
static QSqlDatabase dbMySQL;
und im Code qcsql.cpp
in keiner Funktion usw. also wieder global einQSqlDatabase QCSql::dbMySQL = QSqlDatabase::addDatabase("QMYSQL");
qcsqlite.h
static QSqlDatabase dbSQLite;
qcsqlite.cpp
QSqlDatabase QcSQLite::dbSQLite = QSqlDatabase::addDatabase("QSQLITE");
In mein Hauptcode greife ich über Klassen auf die jeweilige Funktionen zu.
Als erstes wird auf die SQLite zugegriffen, dort erscheint keine Fehlermeldung.
Wenn ich aber auf die MYSQL Funktionen zugreife, erhalte ich die Fehlermeldung "driver not loaded".
Diese Meldung kommt aber unabhängig ob ich auf die SQLite zugegriffen habe oder nicht, sobald SQLITE als static deklariert wurde, geht der Zugriff einfach auf MySQL nicht mehr.Wenn ich SQLITE nicht als static deklariere sondern den Treiber in den Header Initializiere, klappt der Zugriff auf der MySQL, allerdings darf man dann voher nicht SQLITE benutzt haben. Sobald ich SQLITE verwende geht der Zugriff auf der MySQL nicht mehr mit der Fehlermeldung "driver not loaded".
Im Hauptprogramm cpp
In einer Funktion ....QcSQLite qcsqlite; QStringList lastConnectInfoList = qcsqlite.GetLastConnectionsServer(); // Zugriff auf SQLite
In einer anderen Funktion Zugriff auf MySQL
QCSql qcsql; QSqlQuery query(qcsql.mysqlquery(myquery));
Wobei die SQLite beim ersten Aufruf automatisch aufgerufen wird und die der MySQL nur nach bedarf.
@knasan said in Richtiger Umgang mit QSqlDatabase:
QSqlDatabase::addDatabase("QSQLITE")
Ich würde beiden Datenbanken einen eindeutigen Namen geben, sonst überschreibt der zweite Aufruf von addDatabase() die Default-Verbindung.
-
@knasan "Sobald ich die QSQLITE auch als Static deklariere" - als weiter statische Variable? So
QSqlDatabase MySqlConnect:sqldb1 = QSqlDatabase::addDatabase("QMYSQL", "first"); QSqlDatabase MySqlConnect:sqldb2 = QSqlDatabase::addDatabase("QSQLITE", "second");
?
Man kann ja nicht die gleiche sqldb Variable für mehr als eine Verbindung zur gleichen Zeit benutzen.
Ehrlich gesagt verstehe ich immer noch nicht varum diese Variable überhaupt benötigt wird? Man kann eine Verbindung jeder Zeit von QSqlDatabase über ihren Namen bekommen. Wozu also der ganze Aufwand?@jsulm said in Richtiger Umgang mit QSqlDatabase:
Man kann eine Verbindung jeder Zeit von QSqlDatabase über ihren Namen bekommen. Wozu also der ganze Aufwand?
Das habe ich irgendwie übersehen sorry. Ich bin ein C++ Neuling und auch Qt ist für mich noch fremd. Deswegen weiß ich leider noch nicht was falsch und was richtig ist, deshalb hab ich mich an dieses Forum gewand damit ich es Lerne. (Eine C++ Schulung inkl. Qt ist in Planung)
Bitte entschuldige also wenn ich Dumme Fragen stelle.
Wie ist das gemeint, ich kann die Verbindung über den Namen bekommen? Über den ConnectionName?
Kannst du mir ein Link nennen oder ein kleines einfaches Example schreiben wo das ersichtlich ist was du meinst?Gruß und Danke
-
@jsulm said in Richtiger Umgang mit QSqlDatabase:
Man kann eine Verbindung jeder Zeit von QSqlDatabase über ihren Namen bekommen. Wozu also der ganze Aufwand?
Das habe ich irgendwie übersehen sorry. Ich bin ein C++ Neuling und auch Qt ist für mich noch fremd. Deswegen weiß ich leider noch nicht was falsch und was richtig ist, deshalb hab ich mich an dieses Forum gewand damit ich es Lerne. (Eine C++ Schulung inkl. Qt ist in Planung)
Bitte entschuldige also wenn ich Dumme Fragen stelle.
Wie ist das gemeint, ich kann die Verbindung über den Namen bekommen? Über den ConnectionName?
Kannst du mir ein Link nennen oder ein kleines einfaches Example schreiben wo das ersichtlich ist was du meinst?Gruß und Danke
@knasan Es gibt keine dummen Fragen nur dumme Antworten :-)
// Datenbankverbindung einmalig initialisieren und ihr einen namen geben (hier "my_db") QSqlDatabase db = QSqlDatabase::addDatabase("QPSQL", "my_db"); db.setHostName("acidalia"); db.setDatabaseName("customdb"); db.setUserName("mojito"); db.setPassword("J0a1m8"); bool ok = db.open(); // Dann später überall dort wo die Verbindung benötigt wird: QSqlDatabase db = QSqlDatabase::database("my_db");