当前位置: 首页 > news >正文

QT M/V架构开发实战:QSqlQueryModel/ QSqlTableModel/ QSqlRelationalTableModel介绍

目录

    • @[TOC](目录)
  • 前言
  • 一、初步介绍
  • 二、QSqlQueryModel
      • 1.基础定位
      • 2.特点
      • 3.核心接口
      • 4.典型用法
      • 5.优缺点
  • 三、QSqlTableModel
      • 1.基础定位
      • 2.特点
      • 3.核心接口
      • 4.典型用法
      • 5.优缺点
  • 四、QSqlRelationalTableModel
      • 1.基础定位
      • 2.特点
      • 3.核心接口
      • 4.典型用法 (示例:employees表有 dept_id外键,关联 departments表的 id和 name字段)
      • 5.优缺点
  • 五、重要注意事项

前言


本文主要介绍的是使用代码生成的情况下对控件的介绍,包括拥有的功能及能修改的样式,也会说明在qtdesiner拖拽控件生成和使用代码生成控件的区别(如果有的话,遇到了的会说),此版本不属于最终版本,以后遇到什么新奇的点会继续更新!本文基于QT官方的文档进行的编写,QT版本为qt 5.14.0,编写环境为Windows11。不得不说官方文档真是个好东西,有时候有些不会的上去一看就能有灵感解决了,可惜没有中文版本的。

一、初步介绍

因为这三个模型类基本都是将SQL数据库中的数据引入模型的,用到的机会也不是很多,所以就放在一起介绍了。

​核心目标:​​ 将数据库查询结果或表数据无缝展示在 Qt 的视图控件(如 QTableView、QListView)中,并支持一定程度的数据操作(编辑、插入、删除)。

​​共同基础:​​
​​依赖 Qt SQL 模块:​​ 使用前需包含 ,并在项目文件 (.pro) 中添加 QT += sql。
​​需要数据库连接:​​ 使用前必须建立有效的数据库连接 (QSqlDatabase)。
​​视图绑定:​​ 通过 view->setModel(model)将模型绑定到视图。
​​数据角色:​​ 通过 data(index, role)获取数据,支持 Qt::DisplayRole(显示文本)、Qt::EditRole(编辑值) 等。
​​只读属性:​​ QSqlQueryModel默认是只读的。QSqlTableModel和 QSqlRelationalTableModel默认是可编辑的(需设置 setEditStrategy)。
​​列与字段映射:​​ 模型中的列 (column) 对应 SQL 查询结果或数据库表中的字段 (field)。

二、QSqlQueryModel

1.基础定位

​​ 用于执行任意 SQL SELECT查询并将结果集展示在视图中。​​核心是执行查询并获取结果。​​

2.特点

只读 (默认):​​ 仅用于显示查询结果,不支持通过模型直接修改数据、插入或删除行。

​​灵活性高:​​ 可以执行任何 SELECT语句,包括多表连接、聚合函数、子查询等复杂查询。

​​轻量:​​ 主要职责是执行查询和缓存结果。

​​手动刷新:​​ 调用 setQuery()执行新查询来刷新数据。不自动监听数据库变化。

3.核心接口

// 设置/执行查询 (刷新模型)
void setQuery(const QSqlQuery &query);
void setQuery(const QString &query, const QSqlDatabase &db = QSqlDatabase());// 获取底层查询对象
QSqlQuery query() const;// 获取记录 (行) 信息
QSqlRecord record() const; // 返回一个空记录,包含字段信息
QSqlRecord record(int row) const; // 获取指定行的记录 (包含所有字段值)// 获取字段名 (列名)
QString headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override;
// 通常需要重写 headerData() 来设置列标题为字段名

4.典型用法

QSqlQueryModel *model = new QSqlQueryModel;
model->setQuery("SELECT id, name, salary FROM employees WHERE department = 'Sales'", myDatabase);
tableView->setModel(model);
// 重写 headerData 以显示字段名

5.优缺点

优点: 灵活,能处理复杂查询。
缺点: 只读,需要手动刷新,不直接支持编辑。

三、QSqlTableModel

1.基础定位

专门用于操作​​单个数据库表​​。提供对表中数据的​​读写​​访问(CRUD:Create, Read, Update, Delete)。

2.特点

可读写 (默认):​​ 支持通过模型接口 (setData, insertRow, removeRow) 修改数据、插入新行、删除行。

​​基于单表:​​ 操作对象是数据库中的一个表。

​​编辑策略 (EditStrategy):​​ 控制修改如何提交到数据库,是核心特性!
QSqlTableModel::OnFieldChange:字段值改变时立即提交。(​​不推荐​​,效率低且易出错)。
QSqlTableModel::OnRowChange:当用户选择另一行或调用 submit()时提交当前行的所有修改。(常用)。
QSqlTableModel::OnManualSubmit:所有修改都缓存在模型中,直到显式调用 submitAll()或 revertAll()。(最常用,提供事务控制)。

​​过滤与排序:​​ 支持通过 setFilter()设置 WHERE 条件,setSort()设置 ORDER BY 条件。调用 select()应用过滤/排序并刷新数据。

​​自动生成 SQL:​​ 模型内部根据操作自动生成相应的 INSERT, UPDATE, DELETE语句。

3.核心接口

// 设置操作的表和数据库
void setTable(const QString &tableName);
void setDatabase(const QSqlDatabase &db); // 通常在构造函数设置// 设置编辑策略
void setEditStrategy(QSqlTableModel::EditStrategy strategy);// 执行 SELECT 查询 (应用过滤/排序,刷新数据)
bool select();// 设置过滤条件 (WHERE 子句,不带 WHERE 关键字)
void setFilter(const QString &filter);
// 设置排序 (ORDER BY 子句,不带 ORDER BY 关键字)
void setSort(int column, Qt::SortOrder order);// 数据操作
bool insertRow(int row, const QModelIndex &parent = QModelIndex()); // 插入空行
bool removeRow(int row, const QModelIndex &parent = QModelIndex()); // 删除行
bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole) override; // 修改单元格// 提交/回滚修改 (根据 EditStrategy)
bool submit(); // 提交当前行修改 (OnRowChange)
bool submitAll(); // 提交所有缓存的修改 (OnManualSubmit)
void revert(); // 回滚当前行修改
void revertAll(); // 回滚所有缓存的修改// 获取表结构信息
QSqlRecord record() const; // 返回一个空记录,包含字段信息
QSqlRecord record(int row) const; // 获取指定行的记录
QString fieldName(int column) const; // 获取列名 (字段名)

4.典型用法

QSqlTableModel *model = new QSqlTableModel(parent, myDatabase);
model->setTable("employees");
model->setEditStrategy(QSqlTableModel::OnManualSubmit); // 推荐
model->setFilter("department = 'Sales'"); // 设置过滤
model->setSort(2, Qt::AscendingOrder); // 按第3列(索引2)升序
model->select(); // 执行查询,加载数据tableView->setModel(model);
tableView->setEditTriggers(QAbstractItemView::DoubleClicked); // 启用视图编辑// 点击保存按钮时提交所有修改
connect(saveButton, &QPushButton::clicked, model, &QSqlTableModel::submitAll);
// 点击取消按钮时回滚所有修改
connect(cancelButton, &QPushButton::clicked, model, &QSqlTableModel::revertAll);

5.优缺点

优点: 支持对单表进行完整的 CRUD 操作,集成度高,使用相对方便。
缺点: 仅限于单表操作。复杂查询(如多表 JOIN)需要绕行或使用其他模型。OnManualSubmit需要手动管理提交。

四、QSqlRelationalTableModel

1.基础定位

继承自 QSqlTableModel。专门用于处理具有​​外键 (Foreign Key)​​ 关系的单表。它允许你在显示主表记录时,用另一个关联表(Lookup Table)中的​​友好名称​​代替原始的外键 ID 值。

2.特点

继承 QSqlTableModel:​​ 拥有 QSqlTableModel的所有功能(CRUD、过滤、排序、编辑策略)。

​​关系映射 (Relation):​​ 核心功能! 将主表中的外键字段映射到关联表的某个字段(通常是显示名称)。

​​下拉框支持:​​ 在可编辑的视图(如 QTableView)中,编辑具有关系的字段时,会自动提供一个下拉框 (QComboBox),列出关联表中的可选值。

​​内部使用 JOIN:​​ 为了实现关系显示,模型内部在执行 SELECT时会使用 LEFT JOIN(或类似)将关联表连接进来。

3.核心接口

// 设置关系 (核心!)
void setRelation(int column, const QSqlRelation &relation);
// QSqlRelation 构造函数: QSqlRelation(tableName, fieldId, fieldDisplay)
//   tableName: 关联表名
//   fieldId: 关联表中与主表外键字段匹配的 ID 字段 (通常是主键)
//   fieldDisplay: 关联表中要显示的友好名称字段// 获取关系
QSqlRelation relation(int column) const;// 获取关联表的模型 (可用于自定义委托等)
QSqlTableModel *relationModel(int column) const;

4.典型用法 (示例:employees表有 dept_id外键,关联 departments表的 id和 name字段)

QSqlRelationalTableModel *model = new QSqlRelationalTableModel(parent, myDatabase);
model->setTable("employees");
model->setEditStrategy(QSqlTableModel::OnManualSubmit);// 设置关系:将 employees 表的第3列 (假设是 dept_id) 映射到 departments 表的 name 字段
model->setRelation(3, QSqlRelation("departments", "id", "name"));model->select();tableView->setModel(model);// 为了让关系列显示友好名称并使用下拉框,通常需要设置一个特殊的委托
tableView->setItemDelegate(new QSqlRelationalDelegate(tableView));/*
​效果:​​
在 tableView中,原本显示 dept_id(如 1, 2) 的列,现在会显示对应的部门名称 (如 "Sales", "Engineering")。
当用户双击该列进行编辑时,会出现一个下拉框 (QComboBox),列出 departments表中所有的 name值供用户选择。用户选择后,模型内部实际存储和操作的仍然是 dept_id。
*/

5.优缺点

优点: 极大地提升了用户界面友好度,尤其是在处理外键关系时。简化了基于外键的选择操作。
缺点: 仍然基于单表(主表),复杂关系或多表 JOIN 显示非友好名称字段可能力不从心。性能可能略低于 QSqlTableModel(因为 JOIN 操作)。

五、重要注意事项

1、事务管理:​​ QSqlTableModel和 QSqlRelationalTableModel的 submitAll()操作通常发生在数据库事务之外。如果需要严格的原子性操作,应在调用 submitAll()前后手动管理 QSqlDatabase的事务 (transaction(), commit(), rollback())。

​​2、性能:​​ 对于大型数据集,QSqlTableModel和 QSqlRelationalTableModel默认会一次性加载所有数据到内存。考虑使用 setQuery分页 (对 QSqlQueryModel) 或限制过滤条件来优化。

3、​​复杂场景:​​ 对于非常复杂的数据库交互(如涉及多个表深度修改、存储过程调用、特定数据库特性),直接使用 QSqlQuery结合自定义模型 (QAbstractItemModel) 可能是更灵活的选择。

​​4、委托:​​ QSqlRelationalDelegate对于关系列的编辑体验至关重要。你也可以创建自定义委托来实现更复杂的关系编辑逻辑。

本次分享就到这里了,如果有什么错误的话请指正,或者有什么疑问的,也可以在评论区一起探讨!


文章转载自:

http://lvfgw4iX.wztnh.cn
http://lsDnj9qY.wztnh.cn
http://lsu9DqBp.wztnh.cn
http://q99rFi8m.wztnh.cn
http://NlhC9gg5.wztnh.cn
http://5OKyMFrC.wztnh.cn
http://wB4gZ4bJ.wztnh.cn
http://1K8AgtGI.wztnh.cn
http://7bbnoswB.wztnh.cn
http://KYEIIasC.wztnh.cn
http://cbtZSU2I.wztnh.cn
http://TTrNhdah.wztnh.cn
http://cepmRvqz.wztnh.cn
http://rukR2TU8.wztnh.cn
http://gAD3Scli.wztnh.cn
http://uuKVRITI.wztnh.cn
http://2PpMIvpP.wztnh.cn
http://1JI1zrOY.wztnh.cn
http://oLtdjHY9.wztnh.cn
http://ayO5pVrK.wztnh.cn
http://h1Xa9xNt.wztnh.cn
http://YTKDQiIS.wztnh.cn
http://ghrl5Fbn.wztnh.cn
http://UIzs3VY9.wztnh.cn
http://LvX7STcS.wztnh.cn
http://5b7cVPHK.wztnh.cn
http://WlVxZqtB.wztnh.cn
http://UQe26qO5.wztnh.cn
http://NvYwR5RO.wztnh.cn
http://Gxg1gatp.wztnh.cn
http://www.dtcms.com/a/380252.html

相关文章:

  • 网络编程入门:构建你的第一个客户端-服务器应用
  • 极简灰度发布实现新老风控系统切流
  • 基于跳跃表的zset实现解析(lua版)
  • 【学习K230-例程18】GT6700-HTTP-Server
  • Redis列表(List):实现队列/栈的利器,底层原理与实战
  • 超级流水线和标量流水线的原理
  • 漫谈《数字图像处理》之边缘检测与边界预处理的辨析
  • (二)文件管理-文件查看-less命令的使用
  • 深入理解节流(Throttle):原理、实现与应用场景
  • 汽车电子电气架构中的电源架构(下)
  • GISBox与GeoServer使用体验全对比:轻量化工具如何重新定义GIS价值?
  • 02.【Linux系统编程】Linux权限(root超级用户和普通用户、创建普通用户、sudo短暂提权、权限概念、权限修改、粘滞位)
  • JavaEE 初阶第二十二期:网络原理,底层框架的“通关密码”(二)
  • Netty 实战应用:从 RPC 到即时通讯,再到 WebSocket
  • 南京方言数据集|300小时高质量自然对话音频|专业录音棚采集|方言语音识别模型训练|情感计算研究|方言保护文化遗产数字化|语音情感识别|方言对话系统开发
  • Django全栈班v1.04 Python基础语法 20250912 下午
  • uniapp多端打包样式处理
  • Unity学习----【进阶】TextMeshPro学习(一)--基础知识点
  • Echarts雷达图根据数值确定颜色
  • etcd备份脚本
  • 基于 OpenCV 与 SIFT 算法的指纹识别系统实现:从匹配到可视化
  • uniapp微信小程序保存海报到手机相册canvas
  • 3227. 字符串元音游戏
  • 【python实用小脚本-215】[硬件互联] 按钮×Python梦幻联动|用20行代码实现“一键录音”自动化改造实录(建议收藏)
  • 分布式专题——10.2 ShardingSphere-JDBC分库分表实战与讲解
  • 机器学习-数据标注
  • Leetcode:动态规划算法
  • 鸿蒙项目篇-22-项目功能结构说明-写子页面和导航页面
  • 深入解析 Kubernetes 中的 Service 资源:为应用提供稳定的网络访问
  • JAiRouter 0.8.0 发布:Docker 全自动化交付 + 多架构镜像,一键上线不是梦