我正在尝试创建一个类,它应该处理来自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();
}
database.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
database.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对象中,而是每次调用类中的函数时,因为.
Database::Database(QObject *parent) :
QObject(parent)
{
m_db = QSqlDatabase::addDatabase("QSQLITE");
m_db.setHostName("localhost");
m_db.setDatabaseName(QCoreApplication::applicationDirPath() + "/events.db");
}
每次都执行...codeblock。当前的默认连接刚刚被替换,因为新的连接是相同的,这对程序没有任何影响,但它看起来不像是一个整洁的解决方案。
所以我试着用一个可以从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();
}
database.cpp
void Database::declare(QString driver, QString host, QString path)
{
m_db = QSqlDatabase::addDatabase(driver);
m_db.setHostName(host);
m_db.setDatabaseName(path);
}
...but - m_db对象的值当然只能在声明函数中使用,而不能用于我随后调用的其他函数。
我对解决方案的最佳猜测是在main.cpp中声明main.cpp并将其交给它应该调用的函数:
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();
}
database.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));
}
发布于 2013-02-15 14:46:31
我会坚持你的原始代码来解释。
免责声明:我没有编译我的任何建议,如果有语法错误请原谅。
首先,您可能需要的是单例模式 (我不再那么喜欢它了,但就您的目的而言,可以说它可以被认为是合适的):
在您的类定义中必须有以下内容:
class Database : public QObject
{
Q_OBJECT
public:
static Database* instance();
private:
static Database* m_instance;
Database();
~Database() {}; // it can be necessary to have this public in some cases, if
// you ever get a linker error related to deletion, this is
// probably the reason.
public:
// FUNCTIONS
...
};
以及.cpp文件中的以下内容:
// init singleton pointer to NULL
Database* Database::m_instance = NULL;
Database* Database::instance()
{
if( !m_instance )
{
m_instance = new Database();
}
return m_instance;
}
然后,您可以访问该单例使用。
if( Database::instance()->createStructure() )
{
w.show();
}
这是干什么用的?在程序开始时,行
Database* Database::m_instance = NULL;
将m_instance变量初始化为NULL
。第一次调用Database::instance()
时,它会意识到m_instance仍然是空的,并创建了一个新对象,并使m_instance
指向该对象。从那时起,指向该对象的指针将始终被返回,但不会创建更多的Database
对象。
在您的createStructure()
函数中,即使有错误,也可以使用commit()
数据库。通常的程序是在成功时使用commit()
,在失败时使用rollback()
。在解决这个问题之前,请务必阅读下一点:
我建议的第三件事是,每当你经常看到相同行的多次出现时,就习惯于怀疑。通常需要一个子函数。
我说的是
Database::close();
return false;
看看我是如何通过引入另一个方法来重写您的createStructure()
方法的,并且在没有必要的地方省略了else{ }
:
bool Database::createStructure()
{
QStringList commands;
commands.append("CREATE TABLE...;");
commands.append("CREATE TABLE...;");
commands.append("CREATE TABLE...;");
if (!Database::open()) return false;
// at this point you can be sure the database is open
if (!Database::transaction())
{
Database::close();
return false;
}
// at this point you can be sure the database is open and a transaction was started
if (!Database::executeCommands(commands))
{
// an error occurred - we need to rollback what we did so far
Database::rollback();
Database::close();
return false;
}
// everything was executed properly, but the transaction is still active
// => commit the changes we've made
bool committed = Database::commit();
// no matter if the commit was successful or not, close the database,
// then return the result we've stored
Database::close();
return committed;
}
bool Database::executeCommands(const QStringList& commands)
{
// This method simply executes the queries and is relieved from
// transaction-related code.
foreach(QString command, commands)
{
QSqlQuery query;
bool prepared = query.prepare(command);
if(!prepared) return false;
if(!query.exec()) return false;
}
return true;
}
这可以进一步重构,这只是一个例子,使您的代码更容易遵循,因此通常不容易出错。
https://stackoverflow.com/questions/14890751
复制相似问题