使用QSqlRelationalTableModel简化在Qt中使用数据库的工作

美好的一天,哈布罗夫斯克! 在本文中,我想谈谈在使用Qt跨平台库的QSqlRelationalTableModel类开发桌面应用程序时简化与SQL数据库交互的经验。

序言


当我还是一名一年级学生的时候,我遇到了Qt,刚开始使用C ++进行编程,与此同时,我对库也产生了浓厚的兴趣,从那时起,我一直在关注库的更新。 几个月前,在工作中,他们给了我一个TOR,有必要在其中开发与SQLite数据库进行交互的应用程序。 基地的结构是固定的,我事先从TK那里就知道了。

该应用程序应该能够方便操作员显示存储在数据库中的数据,以允许添加新记录,删除和修改现有记录。

接下来,我将简要介绍代码片段的开发过程,并尝试合理地解释为什么在这种情况下选择使用QSqlRelationalTableModel的原因

开发开始


最初,决定使用简单的数据库查询来建立与数据库的交互,即 SELECTINSERTDELETE ,它们使您可以实现应用程序的所有必需功能。

为此,我们需要QSqlDatabaseQSQlQuery类

QSqlDatabase db; //    db = QSqlDatabase::addDatabase("QSQLITE"); //    db.setHostName("localhost"); //  ,    db.setDatabaseName(path); //QString path -    //   if(db.open()){ qDebug() << "db opened OK..."; }else{ qDebug() << " db opening failed..."; } }else{ qDebug() << "file doesnot exist"; exit(0); // ,     , //   } 

之后,对数据库的所有操作将按以下方式执行:

 // ,    <b>QLineEdit</b>' QString query = "INSERT INTO Table (column) VALUES ('" + ui->Input->text() + "')"; QSqlQuery sqlQuery(db); //c   qDebug() << "QUERY: " << query; // //   if(sqlQuery.exec(query)){ qDebug() << "query failed..."; } else{ qDebug() << "query failed..."; } 

Select语句的执行方式类似,不同之处在于仍需要接收数据并将其放置在某处:

 QString query = "SELECT id, ka FROM Table"; QSqlQuery sqlQ(db); if(!sqlQ.exec(query)) { qDebug() << "query failed..."; return; } //     // ,        while (sqlQ.next()){ //           ui->ComboBox->addItem(sqlQ.value(1).toString(),sqlQ.value(0).toInt()); } 

删除语句的执行方式与插入语句完全相同,因为它们不返回任何内容。

好吧,怎么了?


事实是,您可以通过这些表达式和查询实现所有内容, 为什么我们需要模型?

当我们有一个不相关的表时,一切似乎都很简单,不需要引入其他工具。 现在假设我们有这样的表,例如5,每个表有5列,不包括id。 并且每个人都通过id使用外键与前一个人建立联系,即 删除时,有必要级联删除所有“子”记录。 这会导致大量请求,应用程序的工作会大大减慢速度,此外,每次都需要更新表及其在界面中的表示形式,从而导致编写用于更新的其他功能,错误的出现或出现错误的风险,并且通常会降低可读性代码。

因此,在开发过程中,我不得不放弃使用裸SQL查询的概念。

还选择了QSqlRelationalTableModelQTableView进行选择 。 有一个更简单的模型实现版本-QSqlTableModel ,第一个继承自它,它具有所有相同的方法,但是增加了创建QSqlRelation连接的功能,如果用户不需要显示记录ID,而是显示记录“父”的名称,这将非常方便。已连接。

让我们看一下模型的实现


这是一些Pod摘录,显示了模型/视图的实现。

在头文件中:

 QSqlRelationalTableModel *model; 

在构造函数中:

 //  ,    //  QTableView  ,    //QModelIndex     ,      connect(ui->tableView, SIGNAL(clicked(const QModelIndex &)), this, SLOT(onTableClicked(const QModelIndex &))); model = new QSqlRelationalTableModel(parent, db); // , QSqlDatabase    model->setTable("Table"); //    

下面的代码行包含了该模型相对于sql查询而言最方便的功能和优势-在从QTableView更改为QTableView时,它根据上下文编辑,添加,删除sql表中的数据。 方便之处在于,您不再需要控制级联数据删除和在单个QTableView中更新它们的正确性。

 model->setEditStrategy(QSqlRelationalTableModel::OnFieldChange); 

接下来是此类提供的另一个便利功能:在不同表的两列之间建立连接:

 //ParentTable - ,      //id - ,         //name - ,        model->setRelation(1,QSqlRelation("ParentTable", "id", "name")); 

此外,一切都更加标准:select()将执行SELECT语句,而setHeaderData()将在QTableView标头中设置文本:

 model->select(); model->setHeaderData(0, Qt::Horizontal, tr("id")); model->setHeaderData(1, Qt::Horizontal, tr("id_sub")); model->setHeaderData(2, Qt::Horizontal, tr("count")); model->setHeaderData(3, Qt::Horizontal, tr("number")); model->setHeaderData(4, Qt::Horizontal, tr("data_word")); model->setHeaderData(5, Qt::Horizontal, tr("time")); model->setHeaderData(6, Qt::Horizontal, tr("name")); model->setHeaderData(7, Qt::Horizontal, tr("description")); ui->tableView->setModel(model); //     QTableView 

现在,模型和tableView可以一起工作并执行其功能。 指向github的链接将保留所有源代码,在其中我实现了在模型中添加条目,删除它以及过滤器的操作。

结论


在本文中,我想鼓励所有已经在Qt中使用数据库的人放弃对复杂度至少为中等的项目的裸sql查询,而转而使用模型以简化其工作,使代码更具可读性和通用性,只是做点好事和新事物。

仅此而已! 我希望我在这些课程上的经验能帮助读者成功解决类似的问题!

Source: https://habr.com/ru/post/zh-CN435134/


All Articles