sqlite データベースとの間のすべてのデータを処理するクラスを作成しようとしています。ただし、私は QT と C++ にかなり慣れていないため、クラス内のデータベース オブジェクトの宣言について疑問に思っています。私が行っている正しいことと間違っていること、および通常はどのように行うべきか、または行うことができるかについて、いくつかのヒントが必要になる場合があります。私の目標は、クラス用に単一の QSqlDatabase を作成し、それをクラス内のすべての関数に使用することでした。
現時点では、次のコードがあります。
main.cpp
#include "mainwindow.h"
#include "database.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
Database db;
MainWindow w;
if(db.createStructure())
{
w.show();
}
return a.exec();
}
データベース.h
#ifndef DATABASE_H
#define DATABASE_H
#include <QObject>
#include <QSqlDatabase>
class Database : public QObject
{
Q_OBJECT
public:
explicit Database(QObject *parent = 0);
// FUNCTIONS
bool createStructure();
signals:
public slots:
private:
// VARIABLES
QSqlDatabase m_db;
// FUNCTIONS
bool open();
void close();
bool transaction();
bool commit();
};
#endif // DATABASE_H
データベース.cpp
#include "database.h"
#include <QCoreApplication>
#include <QSqlDatabase>
#include <QSqlQuery>
#include <QSqlError>
#include <QList>
Database::Database(QObject *parent) :
QObject(parent)
{
m_db = QSqlDatabase::addDatabase("QSQLITE");
m_db.setHostName("localhost");
m_db.setDatabaseName(QCoreApplication::applicationDirPath() + "/events.db");
}
// PRIVATE
bool Database::open()
{
return m_db.open();
}
void Database::close()
{
return m_db.close();
}
bool Database::transaction()
{
return m_db.transaction();
}
bool Database::commit()
{
return m_db.commit();
}
// PUBLIC
bool Database::createStructure()
{
bool prepared;
QList<QString> commands;
commands.append("CREATE TABLE...;");
commands.append("CREATE TABLE...;");
commands.append("CREATE TABLE...;");
if (!Database::open())
{
return false;
}
else
{
if (!Database::transaction())
{
Database::close();
return false;
}
else
{
foreach(QString command, commands)
{
QSqlQuery query;
prepared = query.prepare(command);
if(!prepared)
{
if (!Database::commit())
{
Database::close();
return false;
}
else
{
Database::close();
return false;
}
}
else
{
if(!query.exec())
{
if (!Database::commit())
{
Database::close();
return false;
}
else
{
Database::close();
return false;
}
}
}
}
if (!Database::commit())
{
Database::close();
return false;
}
else
{
Database::close();
return true;
}
}
}
}
このコードは機能しています。
ただし、QSQLITE データベースは m_db オブジェクトに 1 回追加されるのではなく、クラス内の関数が呼び出されるたびに追加されます。
Database::Database(QObject *parent) :
QObject(parent)
{
m_db = QSqlDatabase::addDatabase("QSQLITE");
m_db.setHostName("localhost");
m_db.setDatabaseName(QCoreApplication::applicationDirPath() + "/events.db");
}
...コードブロックは毎回実行されます。現在のデフォルトの接続が置き換えられただけで、新しい接続は同じであるため、プログラムには何の影響もありませんが、きちんとした解決策のようには見えません。
そこで、このコードブロックを main.cpp から一度呼び出すことができる宣言関数に置き換えようとしました...
main.cpp
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
Database db;
MainWindow w;
db.declare(“QSQLITE”, “localhost”, QCoreApplication::applicationDirPath() + "/events.db");
if(db.createStructure())
{
w.show();
}
return a.exec();
}
データベース.cpp
void Database::declare(QString driver, QString host, QString path)
{
m_db = QSqlDatabase::addDatabase(driver);
m_db.setHostName(host);
m_db.setDatabaseName(path);
}
...しかし、m_db オブジェクトの値はもちろん、宣言関数内でのみ使用でき、後で呼び出す他の関数では使用できません。
私の最善の解決策は、main.cpp で QSqlDatabase を宣言し、呼び出す関数に渡すことです。
main.cpp
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QSqlDatabase qdb = QSqlDatabase::addDatabase("QSQLITE");
qdb.setHostName("localhost");
qdb.setDatabaseName(QCoreApplication::applicationDirPath() + "/events.db");
Database db;
MainWindow w;
if(db.createStructure(qdb))
{
w.show();
}
return a.exec();
}
データベース.cpp
bool Database::open(QSqlDatabase qdb)
{
return qdb.open();
}
void Database::close(QSqlDatabase qdb)
{
return qdb.close();
}
bool Database::transaction(QSqlDatabase qdb)
{
return qdb.transaction();
}
bool Database::commit(QSqlDatabase qdb)
{
return qdb.commit();
}
bool Database::createStructure(QSqlDatabase qdb)
{
bool prepared;
QList<QString> commands;
commands.append("CREATE TABLE...;");
commands.append("CREATE TABLE...;");
commands.append("CREATE TABLE...;");
if (!Database::open(qdb))
{
return false;
}
else
{
if (!Database::transaction(qdb))
{
Database::close(qdb);
return false;
}
else
{
foreach(QString command, commands)
{
QSqlQuery query;
prepared = query.prepare(command);
if(!prepared)
{
if (!Database::commit(qdb))
{
Database::close(qdb);
return false;
}
else
{
Database::close(qdb);
return false;
}
}
else
{
if(!query.exec())
{
if (!Database::commit(qdb))
{
Database::close(qdb);
return false;
}
else
{
Database::close(qdb);
return false;
}
}
}
}
if (!Database::commit(qdb))
{
Database::close(qdb);
return false;
}
else
{
Database::close(qdb);
return true;
}
}
}
}
再利用可能な QSqlDatabase オブジェクトを何らかの形でクラスに格納することは可能ですか? もしそうなら、どのように?本当にありがとうございました!
編集1
関数を使用しているデザイナーから作成されたコード。
mainwindows.cpp
void MainWindow::on_pushButton_24_clicked()
{
Database db;
bool b = db.createStructure();
QMessageBox::information(this, "test", QString(b));
}