Qt数据库应用解析:驱动类、查询类、模型类、视图类详细介绍与使用指南
csdn 2023-12-05

Qt提供了与数据库联动以开发应用程序的模块。与其他API相比,Qt提供的API更直观,也更容易理解。使用Qt提供的API之前,需要添加如下的头文件。

#include <QtSql>

为使用Qt开发应用程序,与使用C++语言类似,数据库使用SQL语言查询数据。SQL是以特定形式收集、积累、保存数据的数据文件,并从逻辑上查询记录,以准确检测相关信息。

Qt提供的数据库类
数据库类 说明
QSql 使用Qt提供的SQL库的类
QSqlDriverCreatorBase SQL驱动的父类
QSqlDriverCreator 用于指定驱动类型的模板库
QSqlDatabase 用于连接数据库的类
QSqlDriver 用于访问特定SQL数据库的抽象类
QSqlError 告知数据库发生的错误信息的类
QSqlField SQL数据库表格和视图中调整字段的类
QSqlIndex 运行数据库索引的类
QSqlQuery 用于运行SQL语句的类
QSqlRecord 隐藏数据库记录的类
QSqlResult 为访问特定数据库的数据而抽象化的接口类
QSqlQueryModel 为SQL结果和数据模型而仅支持只读模式的类
QSqlRelationalTableModel 使用外键在单一数据表修改数据类型的类
QSqlTableModel 在单一数据库表修改数据模型的类

Qt提供的数据库层可分为如下3种形式:

  • 驱动层(Driver Layer):驱动层是连接SQL API和数据库的层。比如:QSQLDriver、QSqlDriverCreator、QSqlDriverPlugin、QSqlDriverResult等;
  • SQL API层:SQL QPI层时SQL驱动的父类,是访问数据库进行数据操作的层。比如:QSqlDatabase、QSqlQuery等;
  • 用户界面层(User Interface Layer):改成用于连接数据库保存的数据和控件,以提供用户界面。比如:QSqlQueryModel、QSqlTableModel、QSqlRealtionalTableModel等。


关联和支持数据库的驱动

为访问数据库,Qt使用QSqlQuery和QSqlQueryModel类关联特定数据库,并生成列表或操作记录。QSqlDatabase可使用数据库固有用户账号进行关联,同时也可以访问不使用用户账号的数据库。

QSqlDatabase db=QSqlDatabase::addDatabase("QMYSQL");    //生成数据库关联对象,附上数据库驱动名
    
db.setHostName("bigblue");                    //访问远程或本地数据库
db.setDatabaseName("flightdb");
db.setUserName("acarlson");
db.setPassword("1uTbSbAs");
    
bool ok=db.open();                    //使用open()函数,关联数据库

Qt需要驱动以关联数据库,并支持如下数据库:

Qt支持的数据库
驱动名 DBMS
QDB2 IBM DB2(7.1及以上版本)
QIBASE Borland InterBase
QMYSQL MySQL
QOCI Oracle调用接口驱动
QODBC Microsoft SQL Server和其他ODBC
QPSQL PostgreSQL(7.2及以上版本)
QSQLITE2 SQLite version 2
QSQLITE SQLite version 3
QTDS Sybase Asaptive Sever

SQLite是在进程内运行的轻量级数据库,支持所有操作系统平台。在Windows和Linux平台上,可以使用OCI、Oracle、PostgreSQL和MySQL等。

Qt为了关联特定的数据库系统,可以将必须的驱动创建为插件形式,此时需要数据库系统提供的客户端库。

创建Qt配置脚本时,必须标明Linux和Mac OS X平台,以查找客户端库。可参考配置脚本的详细帮助-help选项。

配置脚本无法查找需要的数据库的库和头文件。因此,必须使用数据库客户端-L和头文件-I选项进行指定。Qt常用-qt-sql-<driver>创建数据库驱动,使用-plugin-sql-<driver>创建插件形式的驱动。


使用SQL语句的数据库查询

QSqlQuery类使用SQL语句查询数据库。创建QSqlQuery对象并使用QSqlQuery类的函数exec(),即可执行SQL语句。

QSqlQuery query;
query.exec("SELECT * from employee");

使用结果集(result set)查询数据库

QSqlQuery类支持访问记录的结果集的方法。调用该类提供的函数exec(),QSqlQuery类的指针位于第一个记录指针之前。因此,必须使用函数next()移动指针,使其指向第一个记录。要访问其他记录,则可如下所示,循环使用函数next():

QSqlQuery query;
query.exec("SELECT * from employee");
while(query.next()){
        QString name=query.value(0).toString();
        int salary=query.value(1).toInt();
        qDebug()<<name<<salary;
}

QSqlQuery类的成员函数value()从当前记录返回相关字段值,可以指定C++的各种类型,还可以使用Qt提供的QString和QByteArray类型。其他数据库类型自动映射以适应Qt环境。

使用QSqlQuery类的函数hasFeature()指定Qt支持的数据库特征。通过下列示例代码即可了解数据库支持的结果集大小:

QSqlQuery query;
int numRows;
query.exec("SELECT * from employee");
    
QSqlDatabase defaultDB=QSqlDatabase::database();
if(defaultDB.driver()->hasFeature(QSqlDriver::QuerySize)){
        numRows=query.size();
}else{
        query.last();
        numRows=query.at()+1;
}

插入、修改和删除数据记录

使用QSqlQuery类执行SQL语句。下面是使用INSERT语句插入列表记录的示例代码:

QSqlQuery query;
query.exec("INSERT INTO employee VALUES (100,'Herry',21)");

插入大量记录的方法有两种:通过函数prepare()使用名称绑定,或使用可用位置绑定的占位符:

QSqlQuery query;
query.prepare("INSERT INTO employee VALUES (:id,:name,:age)");
query.bindValue(":id",100);
query.bindValue(":name",'Herry');
query.bindValue(":age",21);
query.exec();

下列示例代码使用位置绑定方法:

QSqlQuery query;
query.prepare("INSERT INTO employee VALUES (?,?,?)");
query.addBindValue(100);
query.addBindValue('Herry');
query.addBindValue(21);
query.exec();

只是有函数prepare()即可插入大量记录。使用函数bindValue()和addBIndValue()后,执行函数exec()指定相关记录的字段。在性能方面,占位符的方法可以指定任意的值。下面是修改记录和删除记录的实例:

QSqlQuery query;
query.exec("UPDATE employee SET name='Herry' where id=100");
query.exec("DELETE FROM employee where id=100");

为使用名称绑定处理QMap等绑定属性,Qt使用如下所示的迭代器方法:

QSqlQuery query;
query.exec("SELECT * from employee");
QMapIterator<QString,QVariant> i(query.boundValues());
while(i.hasNext()){
        i.next();
        qDebug()<<i.key().toUtf8().data()<<i.value().toString().toUtf8().data();
}

通过绑定可以使用QList,如下所示:

QSqlQuery query;
query.exec("SELECT * from employee");
QList<QVariant> list=query.boundValues().values();
for(int i=0;i<list.size();i++){
        qDebug()<<list.at(i).toString().toUtf8().data();
}

事务管理

如果数据库引擎支持事务处理,则可以使用Qt提供的QSqlDriver类的成员函数hasFeature(QSqlDriver::Transactions)指定事务处理。可以使用QSqlDatabase类的成员函数transaction()初始化事务,使用函数commit()提交事务,使用QSqlDatabase类的成员函数rollback()回滚特定事务。

当然,查询事务之前必须启动事务。下面是事务处理示例:

QSqlDatabase::database().transaction();
QSqlQuery query;
query.exec("SELECT * FROM employee");
while(query.next()){
        int id=query.value(0).toInt();
        QString name=query.value(1).toString();
        qDebug()<<id<<name;
}
QSqlDatabase::database().commit();


Model类

为了读写QSqlQuery类和数据库的数据,Qt提供了如下模型方式的类:

读写QSqlQuery类和数据库数据的类
说明
QSqlQueryModel 读取任意SQL查询的模型方式
QSqlTableModel 单一列表中读写数据的模型方式
QSqlRelationalTableModel 支持外键的QSqlTableModel的子类

这些类均继承自QAbstractTableModel类。为了读写数据库的数据,可以关联QListView类和QTableView类等项目视图类控件的项目数据。

这些类将从数据库读取的数据存储为XML文件,能够轻松转换为文件格式,并且容易实现访问数据库读写数据的方式。

QSqlQueryModel类提供的数据库模型方式

QSqlQueryModel类可以很轻易地将访问数据库读取的数据实现为模型方式。下面是在SQL查询上使用模型方式实例:

QSqlQueryModel model;
model.setQuery("SELECT * FROM employee");
for(int i=0;i<model.rowCount();i++){
        int id=model.record(i).value("id").toInt();
        QString name=model.record(i).value("name").toString();
        qDebug<<id<<name;
}

通过QSqlQueryModel类提供的成员函数setQuery()设置SQL查询。调用成员函数record(int)可以读取保存到数据库列表的记录。

QSqlTableModel类的模型方式

QSqlTableModel类可以读写数据库上的单一列表记录:

QSqlTableModel model;
model.setTable("employee");
model.setFilter("id>10");
model.setSort(2,Qt::DescendingOrder);
model.select();
for(int i=0;i<model.rowCount();i++){
        int id=model.record(i).value("id").toInt();
        QString name=model.record(i).value("name").toString();
        qDebug<<id<<name;
}

QSqlTableModel类可以分别搜索、修改每个SQL列表。即使没有SQL语法也可以读取列表数据。通过函数record(int)读取保存到列表的记录数据,使用函数setRecord()修改各行记录。下列实例中,employee表的id字段每次增加10%:

for(int i=0;i<model.rowCount();i++){
        QSqlRecord record=model.record(i);
        double id=record.value("id").toDouble();
        id*=id;
        record.setValue("id",id);                    //设置record
        model.setRecord(i,record);                    //设置model
}

使用继承自QAbstractItemModel类的成员函数data()和setData()。下面是使用setData()函数更新记录的示例:

model.setData(model.index(row,column),100);
model.submitAll();

下面是插入插入记录的示例:

model.insertRows(row,1);                    //添加1行
model.setData(model.index(row,0),10);
model.setData(model.index(row,1),"zhangsan");
model.submitAll();

使用如下方法删除数据:

model.removeRows(row,5);                    //删除5行
model.submitAll();

QSqlRelationalTableModel类的模型方式

QSqlRelationalTableModel类是支持主键的QSqlTableModel类的扩展类。讲一个列表的字段和其他列表主键指定的字段进行1:1映射,支持外键。

下面是使用QSqlRelationalTableModel类设置外键的代码示例:

QSqlRelationalTableModel model;
model.setTable("employee");
model.setRelation(2,QSqlRelation("city","id","name"));
model.setRelation(3,QSqlRelation("country","id","name"));

函数setRelation()用于设置列表之间的关系,指定employee表和city的第2个字段。

如果使用具有读写功能的QSqlRelationalTableModel类,则可以在GUI的视图上使用QSqlRelationDelegate类。使用该类后,视图将提供组合框控件。

QTableView* view=new QTableView();
view->setModel(model);
view->setItemDelegate(new QSqlRelationalDelgate(view));


列表视图应用

QSqlQueryModel类、QSqlTableModel类和QSqlRelationalTableModel类提供在Qt的QListView、QTableView和QTreeView等视图窗口显示数据的方法。

如下所示,使用QTableView类控件,生成基于SQL数据模型方式的视图:

QTableView* view=new QTableView();
view->setModel(model);
view->show();

在支持读写的模式方式下,可以使用函数setEditTriggers()修改字段:

view->setEditTriggers(QAbstractItemView::NoEditTriggers);

在多个视图下使用同一方式修改数据。使用函数setHeaderData()可以设置模型的头标题:

model->setHeaderData(0,Qt::Horizontal,QObject::tr("ID"));
model->setHeaderData(1,Qt::Horizontal,QObject::tr("NAME"));



声明: 本文转载自其它媒体或授权刊载,目的在于信息传递,并不代表本站赞同其观点和对其真实性负责,如有新闻稿件和图片作品的内容、版权以及其它问题的,请联系我们及时删除。(联系我们,邮箱:evan.li@aspencore.com )
0
评论
  • 对话周祖成教授 - 清华大学与西门子EDA的合作之旅


  • 相关技术文库
  • C语言
  • 编程
  • 软件开发
  • 程序
下载排行榜
更多
评测报告
更多
广告