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://www.pswp.cn/bicheng/96678.shtml
繁体地址,请注明出处:http://hk.pswp.cn/bicheng/96678.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Terraform 从入门到实战:历史、原理、功能与阿里云/Azure 上手指南

前言:在云时代,企业的IT基础设施早已从“几台服务器”演变为“横跨多云的复杂网络、计算、存储集群”。但随之而来的,是管理复杂度的爆炸式增长:开发环境和生产环境不一致、手动配置容易出错、多云平台操作方式各异、资源变更难以…

【计算机网络 | 第10篇】信道复用技术

文章目录信道复用技术:高效利用通信资源的智慧方案一、频分复用(FDM):按频率划分的并行通道二、时分复用(TDM):按时间分割的轮流占用三、统计时分复用(STDM):…

安卓13_ROM修改定制化-----禁用 Android 导航按键的几种操作

Android 设备的导航按键通常包括后退键(Back)、主页键(Home)和最近键(Recents),这些按键位于屏幕底部或设备实体区域。禁用导航按键可以帮助在特定应用场景(如信息亭模式或儿童锁模式)中限制用户操作。安卓设备上禁用底部虚拟导航键(返回、主页、多任务键)有多种方法…

通过S参数测量评估电感阻抗:第2部分

S21双端口分流和双端口串联方法 T这是两篇文章中的第二篇,专门讨论使用网络分析仪测量 S 参数进行电感阻抗评估主题。上一篇文章 [1] 描述了阻抗测量和计算S11使用单端口分流器、双端口分流器和双端口串联方法的参数。本文专门介绍阻抗测量和计算S21使用双端口分流…

[deepseek] C语言头文件与汇编实现讨论

我想询问一种代码实现方式,使用C语言,例如main.c包含了自己编写的库文件abc.h,我想问的是:一、abc.h中是否可以有实现函数的代码;二、abc.h中的函数是否可以在另一个后缀为asm的汇编文件中实现?非常好&…

`.cursorrules` 与 `.cursorcontext`:Cursor AI 编程助手时代下的“双轨配置”指南

.cursorrules 与 .cursorcontext:AI 编程助手时代下的“双轨配置”指南关键词:Cursor、AI 编程、上下文管理、开发规范、技术治理 适合读者:前端 / 全栈工程师、技术负责人、AI 辅助编程实践者1. 为什么又多了两个“点”文件? 随着…

XR 和 AI 在 Siggraph 2025 上主导图形的未来,获取gltf/glb格式

Meta 的 Boba 和 Tiramisu XR 耳机(来源:Meta) Siggraph 2025 今年重返不列颠哥伦比亚省温哥华,庆祝《玩具总动员》诞生 30 周年和视频游戏实时渲染 20 周年。虽然 Siggraph 需要时间来欣赏过去,但它更多的是展望未来…

在 Ubuntu 22.04 系统(CUDA 12.9)中,通过本地DEB 包安装 cuDNN 9.13.0 的方法步骤

以下是在 Ubuntu 22.04 系统(CUDA 12.9)中,通过本地单个 DEB 包安装 cuDNN 9.13.0 的完整步骤,核心包含 GPG 密钥配置与包安装验证,确保每一步可执行。 一、安装前核心检查(必做) 确保系统已满足基础条件,避免安装失败: 验证 CUDA 版本:打开终端执行命令,确认当前…

Element 中 upload 编辑回显文件上传信息技巧

文章目录需求分析需求 upload 编辑状态下回显已上传的文件信息 分析 添加fileList <el-uploadstyle"width: 100%"ref"uploadRef"class"upload-demo"action"/prod-api/jc/files/upload"multiple:limit"1":on-success&q…

php简介(第一天打卡)

一.php简介 1.什么是php&#xff1f; 1.1 Php 为什么叫这个名字&#xff1f; Personal home page 最开始用于个人主页建站 后更名为 hypertext preprocessor 超文本预处理 1.2 php是属于哪种语言&#xff1f; 后端语言 &#xff08;从开发角度分类&#xff09; 服务端语言…

Android 车联网——车载仪表屏开发(二十六)

通常汽车启动后需要快速显示仪表,而车载娱乐系统所在的Android系统,启动是比较耗时的,所以通常仪表系统会做在一个小型轻量化的系统内,从而达到快速启动的效果,最终实现汽车一发动,就立刻能显示出仪表必须显示的各项内容。 一、仪表功能介绍 1、仪表的发展 机械仪表:通…

RL--RLHF--PPO--GRPO--DPO速通

参考视频&#xff1a;1小时速通 - 从强化学习到RLHF - 简介_哔哩哔哩_bilibili 强化学习RL RL的核心就是智能体Agent 与 环境Environment的交互。 状态&#xff08;State&#xff0c;s&#xff09;&#xff1a;环境在某一时刻的描述&#xff0c;表示当前情境。动作&#xff0…

hardhat 项目目录介绍

使用 npx hardhat init初始化一个 Hardhat 项目后&#xff0c;会生成一个结构清晰的目录&#xff0c;每个部分都有其特定用途。下面是一个表格汇总了主要的目录和文件及其作用&#xff0c;方便你快速了解&#xff1a;contracts/​​存放项目的 ​​Solidity 智能合约源代码​​…

9.11网编项目——UDP网络聊天

服务器端#include <stdio.h> #include <string.h> #include <stdlib.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #include <errno.h> #include <unistd.h> #include <25061head.h> #d…

第3节-使用表格数据-数据库设计

摘要: 在本教程中&#xff0c;你将学习如何为自己的应用程序设计 PostgreSQL 数据库。 业务需求 我们将为一个简单的库存管理系统设计数据库。 让我们从业务需求开始&#xff1a; “我们的库存管理系统使仓库用户能够高效管理多个仓库的库存。” 它简化了产品管理&#xff0c;使…

Linux下清理磁盘空间——df 磁盘占用100%,du占用很少空间的原因

背景 一台测试服务器&#xff0c;/data磁盘大小为300G&#xff0c;时不时就满了&#xff0c;通过df命令查看300G基本全用了&#xff0c;use 100%。但是进到/data目录中通过du 命令查看&#xff0c;也就用了20个G左右&#xff0c;怎么都对不上。如何清理都没有释放太多空间。查看…

分钟级长视频生成迎来“记忆革命”,7倍成本降低,2.2倍端到端生成速度提升!|斯坦福字节

论文链接&#xff1a;https://arxiv.org/pdf/2508.21058 项目链接&#xff1a;https://primecai.github.io/moc/亮点直击提出了一种自适应上下文混合&#xff08;Adaptive Mixture of Contexts&#xff0c;MoC&#xff09;框架&#xff0c;该框架学习将每个查询路由到视频序列中…

JavaScript 设计模式概览

1. 设计模式是什么? 设计模式是开发中解决常见问题的经典方案。设计模式并非具体代码&#xff0c;而是解决问题的通用解决方案&#xff0c;帮助开发者避免重复造轮子&#xff0c;提升代码的可维护性、可扩展性。 2. 设计模式的历史 设计模式起源于建筑领域&#xff0c;由克…

(九)Spring Cloud Alibaba 2023.x:微服务接口文档统一管理与聚合

目录 前言 准备 实践 网关服务配置 1.pom.xml 引入 webflux 版本 springboc 依赖 2.application-dev.yml 配置 springboc 多服务地址 3.application-dev.yml 配置springboc 文档路由 4.网关过滤器AuthFilter.class 中放行 springboc 访问路径 业务服务配置 1.pom.xml…

在Cursor里安装极其好用的Mysql Database Client 插件

&#x1f4f8; 插件界面展示 图片1&#xff1a;插件主界面和连接配置图片2&#xff1a;数据编辑和查询结果展示&#x1f3af; 核心优势 1. 直接编辑数据 - 像DataGrip一样强大 ✅ 点击即编辑: 直接双击数据单元格&#xff0c;立即进入编辑模式✅ 实时保存: 编辑完成后按 Enter …