Sqlite 'Driver not loaded Driver not loaded'
-
Servus,
habe in meinem neuen Projekt mal versucht, die Datenbankverbindung in eine eigene Klasse auszulagern, das klappt allerdings nicht so, wie ich es mir vorstelle.
Habe vorher immer eine komplett neue Datenbankverbindung hergestellt. Das war redundant ohne Ende, aber dafür hat es funktioniert. So in etwa sah es aus:
.pro
QT += core gui QT += sql ...
.cpp
void Class::insertRecord(QString insert){ db = QSqlDatabase::addDatabase("QSQLITE"); QString databaseName = QCoreApplication::applicationDirPath() + "/db.sqlite"; db.setDatabaseName(databaseName); db.open(); QMessageBox messageBox; // Auf Fehler bei Datenbankverbindung überprüfen if(db.lastError().isValid()){ messageBox.setText("Datenbank Fehler: " + db.lastError().text()); messageBox.setIcon(QMessageBox::Warning); messageBox.exec(); return; } QSqlQuery sql(insert); // Auf Fehler im Statement überprüfen if(sql.lastError().isValid()){ messageBox.setText("Query Fehler: " + sql.lastError().text()); messageBox.setIcon(QMessageBox::Warning); messageBox.exec(); return; } else{ messageBox.setText("Eintrag erfolgreich!"); messageBox.exec(); } db.close(); }
Nun habe ich, wie gesagt, eine eigene Datenbankklasse angelegt, die direkt durch den Konstruktor den Datenbanknamen und den Treiber bekommt. Das Verbinden und Trennen erfolgt durch zwei separate Methoden connect() und disconnect(). Habe natürlich auch die .pro Datei in diesem Projekt entsprechend um QT += sql erweitert.
.h
#ifndef DATABASE_H #define DATABASE_H #include <QString> #include <QtSql> #include "mainwindow.h" class Database { public: Database(); bool connect(); void disconnect(); QSqlQuery query(QString sql); private: QString dbName; QSqlDatabase *db; }; #endif // DATABASE_H
.cpp
Database::Database() { this->dbName = QCoreApplication::applicationDirPath() + "/database.sqlite"; this->db = new QSqlDatabase(); this->db->addDatabase("QSQLITE"); this->db->setDatabaseName(this->dbName); } QSqlQuery Database::query(QString sql){ // Prüfe ob Verbindung bereits hergestellt ist if(!(this->db->isOpen())){ this->connect(); } // Abfrage ausführen QSqlQuery query(sql); // Auf Fehler im Statement überprüfen if(query.lastError().isValid()){ QMessageBox msg; msg.setText("Abfragefehler: " + query.lastError().text()); msg.setIcon(QMessageBox::Warning); msg.exec(); } // Verbindung trennen this->disconnect(); // Abfrage erfolgreich return query; } bool Database::connect(){ // Datenbankverbindung herstellen this->db->open(); // Auf Fehler bei Datenbankverbindung überprüfen if(this->db->lastError().isValid()){ QMessageBox msg; msg.setText("Verbindungsfehler: " + this->db->lastError().text()); msg.setIcon(QMessageBox::Warning); msg.exec(); return false; } return true; } void Database::disconnect(){ // Prüfe ob Verbindung bereits hergestellt ist if(this->db->isOpen()){ this->db->close(); } }
Wenn ich das Programm starte, prüfe ich mit this->db->connect() ob eine Verbindung hergestellt werden konnte. Genau dann erhalte ich den Fehler 'Driver not loaded Driver not loaded'. Natürlich lege ich das Datenbankobjekt an, bevor ich die Methode connect() aufrufe:
this->db = new Database(); this->dbStatus = new QLabel(); if(this->db->connect()){ this->dbStatus->setPixmap(QPixmap(":/images/images/accept.png")); this->dbStatus->setToolTip("Mit Datenbank verbunden"); this->dbStatus->setStatusTip("Mit Datenbank verbunden"); } else{ this->dbStatus->setPixmap(QPixmap(":/images/images/cancel.png")); this->dbStatus->setToolTip("Verbindungsfehler"); this->dbStatus->setStatusTip("Verbindungsfehler"); }
Ich hoffe ihr könnt mir helfen. Verwende Windows XP x86 SP3. Wie gesagt, beim anderen Projekt funktioniert alles wunderbar.
Vielen Dank im Voraus.
Gruß
Kk51
-
Bitte schau dir GENAU an, wie du in den beiden Code-Schnipseln das db-Objekt initialisierst. Im ersten Fall kommt ein brauchbares Objekt, im zweiten ein unbrauchbares raus. Zentrale Rolle hat QSqlDatabase::addDatabase() - dazu auch nochmal die Doku bemühen.
-
Okay, verstehe nicht so ganz worauf du hinaus willst. Also ein Unterschied wäre schonmal, dass das Datenbankobjekt nun dynamisch ist und ich über den Pointer darauf zugreife. Das dürfte aber kein Problem sein, oder? Der andere Unterschied ist, dass ich nun die Methode addDatabase() über mein Objekt direkt aufrufe. Das mache ich aber nur, weil der Zugriff auf die statische Methode bei meinem Objekt nicht mehr funktioniert. Wo liegt mein Denkfehler?
E: Okay, habe das Objekt nun statisch angelegt und nun funktioniert es. Habe mir die Docs entsprechend durchgelesen, bin aber nicht daraus schlau geworden, warum ich kein dynamisches Objekt verwenden darf. Kannst du mir das bitte noch erklären?
So funktioniert es:
h:
QSqlDatabase db;
cpp:
this->dbName = QCoreApplication::applicationDirPath() + "/database.sqlite"; this->db = QSqlDatabase::addDatabase("QSQLITE"); this->db.setDatabaseName(this->dbName);
Danke für deine Hilfe!
-
Karottenkopf51 schrieb:
Okay, verstehe nicht so ganz worauf du hinaus willst. Also ein Unterschied wäre schonmal, dass das Datenbankobjekt nun dynamisch ist und ich über den Pointer darauf zugreife. Das dürfte aber kein Problem sein, oder? Der andere Unterschied ist, dass ich nun die Methode addDatabase() über mein Objekt direkt aufrufe. Das mache ich aber nur, weil der Zugriff auf die statische Methode bei meinem Objekt nicht mehr funktioniert. Wo liegt mein Denkfehler?
Dein Denkfehler liegt darin, dass du meinst, eine statische Methode könnte dein Objekt ändern. static = unabhängig von einer Instanz funktionsfähig. addDatabase() erzeugt einfach ein neues (!) QDatabase-Objekt, richtet es entsprechend der übergebenen Argumente ein und gibt es zurück (!).
Der große Unterschied liegt darin, dass du im ersten Fall korrekt das neu erstellte Objekt deiner lokalen db-Instanz zuweist, im zweiten Fall verwirfst du den Rückgabewert (das gerade erstellte, funktionierte db-Objekt) und arbeitest mit einem ungültigen db-Objekt.
-
Wenn man das so erklärt bekommt, klingt alles sehr schlüssig und nachvollziehbar. Macht ein dynamisches Objekt hier überhaupt Sinn? Im Grunde regel ich ja alles über die Klasse, ich übergebe den Pointer ja nie.
-
Karottenkopf51 schrieb:
Wenn man das so erklärt bekommt, klingt alles sehr schlüssig und nachvollziehbar. Macht ein dynamisches Objekt hier überhaupt Sinn? Im Grunde regel ich ja alles über die Klasse, ich übergebe den Pointer ja nie.
Nein, der pointer macht keinen Sinn.
-
Okay, viele Dank. Denke das ist dann geklärt