gpt4 book ai didi

Qt:类中的QSqlDatabase对象(如何声明?)

转载 作者:行者123 更新时间:2023-12-03 15:59:48 26 4
gpt4 key购买 nike

我正在尝试创建一个应该处理来自和传入 sqlite 数据库的所有数据的类。但是,我对 QT 和 C++ 还很陌生,并且想知道类中数据库对象的声明。我可能需要一些关于我做对与错的提示,以及通常应该或可以如何做的提示。我的目标是为类创建一个单一的 QSqlDatabase 并将其用于类中的每个函数。

目前,我有以下代码:

主文件

#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 对象中,而是每次调用类中的一个函数,因为...
Database::Database(QObject *parent) :
QObject(parent)
{
m_db = QSqlDatabase::addDatabase("QSQLITE");
m_db.setHostName("localhost");
m_db.setDatabaseName(QCoreApplication::applicationDirPath() + "/events.db");
}

...代码块每次都执行。
当前的默认连接只是被替换了,因为新的连接是相同的,这对程序没有任何影响,但它看起来不是一个很好的解决方案。

因此,我尝试用可以从 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 并将其提供给它应该调用的函数:

主文件
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

从我使用函数的设计器创建的一些代码。

主窗口.cpp
void MainWindow::on_pushButton_24_clicked()
{
Database db;
bool b = db.createStructure();

QMessageBox::information(this, "test", QString(b));
}

最佳答案

我会坚持使用您的原始代码进行解释。

免责声明:我没有编译我的任何建议,如果有语法错误,请原谅我。

首先,您可能正在寻找的是 Singleton Pattern (我不再那么喜欢了,但是出于您的目的,有人可能会争辩说它可以被认为是合适的):

您必须在类定义中包含以下内容:

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 仍然是 NULL 并创建一个新对象并使 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;
}

这可以进一步重构,这只是使您的代码更易于遵循的示例,因此通常不易出错。

关于Qt:类中的QSqlDatabase对象(如何声明?),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14890751/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com