Qt-数据库开发-事务提交(3)

news2025/2/27 8:12:35

Qt-数据库开发-通过QSqlTableModel显示和修改数据,开启事务

文章目录

  • Qt-数据库开发-通过QSqlTableModel显示和修改数据,开启事务
    • 1、概述
    • 2、实现效果
    • 3、主要代码
    • 4、完整源代码

更多精彩内容
👉个人内容分类汇总 👈
👉数据库开发 👈

1、概述

  • 这是通过学习Qt官方Demo产生的一个示例;
  • 通过自己理解加入了一些更加详细便于学习的内容;
  • 添加了非常详细的注释信息,对于小白更加友好。

开发环境说明

  • 系统:Windows10、Ubuntu20.04
  • Qt版本:V5.12.5
  • 编译器:MSVC2017-64、GCC/G++64

2、实现效果

  1. 通过QSqlTableModel将数据库内容直接显示到QTableView中,直观的显示和修改数据库中的数据;
  2. 程序启动时自动创建一个数据库,并创建一个表写入默认测试数据,可选择创建文件数据库还是内存数据库;
  3. 写入测试数据时演示了QSqlQuery的五种不同的插入数据方式;
  4. 在界面上修改内容后不会立即保存到数据库中,需要点击提交按键才一次性将所有修改的内容保存到数据库;
  5. 如果在界面上修改了内容,还没有提交事务时可以选择还原所有修改内容。
  • 实现效果如下:

    在这里插入图片描述

3、主要代码

  • 啥也不说了,直接上代码,一切有注释

  • pro文件: Qt使用到数据库,上来什么都别管,先在pro文件添加上QT += sql

  • main.cpp文件:程序第一次启动时在main函数中创建数据库并写入数据;

    #include "widget.h"
    
    #include <QApplication>
    #include <QSqlQuery>
    #include <qmessagebox.h>
    #include <qsqldatabase.h>
    
    /**
     * @brief  创建并打开一个QSqlite数据库,并创建一个测试表person,同时默认创建5组数据
     * @return
     */
    bool createConnection()
    {
        QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE");  // 使用数据库驱动(Qsqlite)和默认连接名称(qt_sql_default_connection)添加一个数据库
    //    qDebug() << QSqlDatabase::defaultConnection;           // 打印默认数据库连接名称
    #if 1
        db.setDatabaseName("test.db");        // 使用文件数据库(可生成数据库文件,数据一直有效)
    #else
        db.setDatabaseName(":memory:");       // 使用内存数据库(不会生成数据库文件,所有数据都在内存中进行操作,性能强,程序退出后数据丢失)
    #endif
    
        if(!db.open())             // 打开数据库
        {
            QMessageBox::critical(nullptr, "Error", "打开数据库失败!");
            return false;
        }
    
        QSqlQuery query;          // 创建一个用于执行和操作Sql语句的对象
    
        // 创建一个表person,包含id、firstname、lastname三个字段
        query.exec("create table person ("
                   "id         int primary  key,"    // 索引
                   "firstname  varchar(20),"         // 名
                   "lastname   varchar(20))");       // 姓
    
        /****************** 向表中插入数据 ************************/
    
        // 插入方式一:直接插入数据
        query.exec("insert into person values(1, '悟空', '孙')");       // INSERT INTO 语法1(为表中所有项插入数据)
    
        // 插入方式二:使用命名占位符的[命名]绑定
        query.prepare("insert into person(id, firstname, lastname)"       // insert into 语法2
                      "values (:id, :firstname, :lastname)");
        query.bindValue(":id", 2);
        query.bindValue(":firstname", "悟净");
        query.bindValue(":lastname", "沙");
        query.exec();
    
        // 插入方式三:使用命名占位符的[位置]绑定
        query.prepare("insert into person(id, firstname, lastname)"       // insert into 语法2
                      "values (:id, :firstname, :lastname)");
        query.bindValue(0, 3);
        query.bindValue(1, "八戒");
        query.bindValue(2, "猪");
        query.exec();
    
        // 插入方式四:使用位置占位符绑定值(版本 1)
        query.prepare("insert into person(id, firstname, lastname)"       // insert into 语法2
                      "values (?, ?, ?)");
        query.bindValue(0, 4);
        query.bindValue(1, "白龙");
        query.bindValue(2, "小");
        query.exec();
    
        // 插入方式五:使用位置占位符绑定值(版本 2)
        query.prepare("insert into person(id, firstname, lastname)"       // insert into 语法2
                      "values (?, ?, ?)");
        query.addBindValue(5);                                           // 使用位置值绑定时,将值val添加到值列表中。addBindValue()调用的顺序决定了在准备好的查询中将值绑定到哪个占位符
        query.addBindValue("三藏");
        query.addBindValue("唐");
        query.exec();
    
        return true;
    }
    
    int main(int argc, char *argv[])
    {
        QApplication a(argc, argv);
    
        if(!createConnection()) return -1;    // 创建并打开一个数据库
    
        Widget w;
        w.show();
        return a.exec();
    }
    
    
  • widget.ui文件: 添加3个QPushButton用于提交和还原数据库事务、1个QTableView用于显示数据库内容;

    在这里插入图片描述

  • widget.h文件

    #ifndef WIDGET_H
    #define WIDGET_H
    
    #include <QWidget>
    class QSqlTableModel;
    
    QT_BEGIN_NAMESPACE
    namespace Ui { class Widget; }
    QT_END_NAMESPACE
    
    class Widget : public QWidget
    {
        Q_OBJECT
    
    public:
        Widget(QWidget *parent = nullptr);
        ~Widget();
    
    
    private slots:
        void on_but_submit_clicked();
    
        void on_but_revert_clicked();
    
        void on_but_quit_clicked();
    
    private:
        Ui::Widget *ui;
        QSqlTableModel* m_model = nullptr;
    };
    #endif // WIDGET_H
    
    
  • widget.cpp文件

    #include "widget.h"
    #include "ui_widget.h"
    
    #include <qmessagebox.h>
    #include <qsqltablemodel.h>
    #include <QSqlError>
    
    Widget::Widget(QWidget *parent)
        : QWidget(parent)
        , ui(new Ui::Widget)
    {
        ui->setupUi(this);
        this->setWindowTitle(QString("QSql-使用事务提交修改内容到数据库Demo - V%1").arg(APP_VERSION));
    
        m_model = new QSqlTableModel(this);
        m_model->setTable("person");         // 设置需要操作的表
        m_model->setEditStrategy(QSqlTableModel::OnManualSubmit);  // 设置数据不自动保存到数据库表
        m_model->select();                   // 查询表中所有数据
    
        ui->tableView->setModel(m_model);
        ui->tableView->resizeColumnsToContents();   // 根据表格中的内容自动调整列宽
    
    }
    
    Widget::~Widget()
    {
        delete ui;
    }
    
    /**
     * @brief 开启sqlite事务并提交修改,相对于直接使用submitAll更有优势(开始事务可以优化写入大量数据速度)
     */
    void Widget::on_but_submit_clicked()
    {
        bool ret = m_model->database().transaction();
        if(!ret) return;
        if(m_model->submitAll())           // 提交所有修改,如果开启了事务,则保存到事务
        {
            m_model->database().commit();  // 如果开启了事务,则将事务保存到数据库
            QMessageBox::about(this, "注意!", "保存修改内容成功!");
        }
        else
        {
            m_model->database().rollback();
            QMessageBox::warning(this, "错误!", QString("数据提交错误:%1").arg(m_model->lastError().text()));
        }
    }
    
    /**
     * @brief 还原所有未提交的修改
     */
    void Widget::on_but_revert_clicked()
    {
        m_model->revertAll();
    }
    
    /**
     * @brief 退出
     */
    void Widget::on_but_quit_clicked()
    {
        this->close();
    }
    

4、完整源代码

  • github
  • gitee

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/75742.html

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

相关文章

毕设选题推荐基于python的django框架的疫苗预约接种管理系统

&#x1f496;&#x1f525;作者主页&#xff1a;计算机毕设老哥&#x1f525; &#x1f496; 精彩专栏推荐订阅&#xff1a;在 下方专栏&#x1f447;&#x1f3fb;&#x1f447;&#x1f3fb;&#x1f447;&#x1f3fb;&#x1f447;&#x1f3fb; Java实战项目专栏 Python实…

新型网络接入控制技术

1.NAC技术 1.1简介 网络接入控制(Network Access Control&#xff0c;简称NAC)是由思科(Cisco)主导的产业级协同研究成果&#xff0c;NAC可以协助保证每一个终端在进入网络前均符合网络安全策略。NAC技术可以提供保证端点设备在接入网络前完全遵循本地网络内需要的安全策略&a…

list容器模拟实现

&#x1f4cb; 个人简介 &#x1f496; 作者简介&#xff1a;大家好&#xff0c;我是菀枯&#x1f61c; &#x1f389; 支持我&#xff1a;点赞&#x1f44d;收藏⭐️留言&#x1f4dd; &#x1f4ac;格言&#xff1a;不要在低谷沉沦自己&#xff0c;不要在高峰上放弃努力&am…

布局福建市场,维也纳酒店欧暇·地中海酒店能否为投资人带来信心与底气?

近日&#xff0c;锦江酒店&#xff08;中国区&#xff09;“一城一海&#xff0c;暇享好时光”——欧暇地中海漳州长泰凯悦广场店开业典礼隆重举办。 与此同时&#xff0c;锦江酒店&#xff08;中国区&#xff09;维也纳酒店&欧暇地中海酒店品牌厦门推介会也圆满落地。在本…

Able2Extract Professional识别引擎经过微调

Able2Extract Professional识别引擎经过微调 改进的表格检测-现在&#xff0c;您可以在自定义PDF到Microsoft Excel转换过程中更准确地确定类似表格结构和内容的位置。 改进了表与列标题的分离-表识别引擎经过改进&#xff0c;可以检测和识别具有单个标题的多列表。 改进的PDF文…

echarts map地图中绘制浙江省市区县乡镇多级联动边界下钻的最新geojson数据文件获取和更新

文章目录ECharts Map地图的显示GeoJSON数据文件获取在ECharts中绘制浙江省的数据ECharts Map地图的显示 ECharts支持地理坐标显示&#xff0c;专门提供了一个geo组件&#xff0c;在setOption中提供option.geo配置即可显示地图。 option.geo配置中有个map属性&#xff0c;取值…

HBase中的Compaction详解

Compaction的作用 由于memstore每次刷写都会生成一个新的HFile&#xff0c;且同一个字段的不同版本&#xff08;timestamp&#xff09;和不同类型&#xff08;Put/Delete&#xff09;有可能会分布在不同的 HFile 中&#xff0c;因此查询时需要遍历所有的 HFile。为了减少 HFile…

PHPMYADMIN 无法编辑 MYSQL 解决方法

本想通过镜像重新把老站点搭建起来拷贝点文章内容,登录后台时发现忘记了密码,想着通过 PHPMyAdmin 修改 Mysql 数据库内容是非常简答的,万万没想到如下图提示错误:#1030 Get error -1 from storage engine,当时就想到可能因 InnoDB 引擎问题导致,查看在 Mysql 的 my.cnf …

C#学习记录——Windows计算器的制作【实例】

参考《C#从入门到项目实践》边学习&#xff0c;边练习实现。 Windows计算器的制作 此次练习的计算器应用软件在Visual Studio 2019编程环境中开发&#xff0c;是一个简单的窗体应用程序&#xff0c;实现简单的计算器功能。 1、系统功能描述 Windows计算器是利用C#程序设计编…

InputStreamReader构造函数的四种方式实现

InputStreamReader类的构造函数 InputStreamReader(InputStream in) //创建InputStreamReader对象&#xff0c;构造方法中传递输入流&#xff0c;使用默认字符集InputStreamReader(InputStream in, String charsetName) //创建InputStreamReader对象&#xff0c;构造方法中传递…

国考省考行测:主体分析法,高频词往往是主体,没有主体也能说语意主旨,故事型材料对比分析法,积极引申大道理

国考省考行测&#xff1a;主体分析法&#xff0c;高频词往往是主体&#xff0c;没有主体也能说语意主旨&#xff0c;故事型材料对比分析法&#xff0c;积极引申大道理 2022找工作是学历、能力和运气的超强结合体! 公务员特招重点就是专业技能&#xff0c;附带行测和申论&#…

Redis主从复制,哨兵模式和集群模式

主从复制 什么是主从复制 主从复制是高可用Redis的基础&#xff0c;哨兵和集群都是在主从复制基础上实现高可用的。主从复制主要实现了数据的多机备份&#xff0c;以及对于读操作的负载均衡和简单的故障恢复。缺陷&#xff1a;故障恢复无法自动化&#xff1b;写操作无法负载均…

JSP ssh网上家具店系统myeclipse开发mysql数据库MVC模式java编程计算机网页设计

一、源码特点 JSP ssh网上家具店系统是一套完善的web设计系统&#xff08;系统采用ssh框架进行设计开发&#xff09;&#xff0c;对理解JSP java编程开发语言有帮助&#xff0c;系统具有完整的源代码和数据库&#xff0c;系统主要采用B/S模 式开发。开发环境为TOMCAT7.0,M…

shell编程(三)--awk

本以为只是个命令&#xff0c;学起来这就是语言么&#xff0c;参看man手册多试吧 格式 awk pattern{action} <file> ​ A pattern can be: ​ BEGIN ​ END ​ expression 示例&#xff1a; ​ awk {print $0} awk.txt ​ print是打印命令&#xff0c;awk.txt是我们为…

JavaScript—实现手风琴画册

✅作者简介&#xff1a;热爱国学的Java后端开发者&#xff0c;修心和技术同步精进。 &#x1f34e;个人主页&#xff1a;Java Fans的博客 &#x1f34a;个人信条&#xff1a;不迁怒&#xff0c;不贰过。小知识&#xff0c;大智慧。 &#x1f49e;当前专栏&#xff1a;前端案例分…

EM算法——投硬币样例实现

理论参考 【机器学习】EM——期望最大&#xff08;非常详细&#xff09; 样例介绍 有c个硬币&#xff0c;每次随机选一个投掷n次&#xff0c;重复执行m次并记录结果。 根据投掷结果计算出每个硬币正面的概率。 每次选择的硬币未知。 过程介绍 随机初始化硬币为正的概率 he…

阿里P8终于整理出:Nginx+jvm+MySQL+Docker+Spring实战技术文档

前言 都说程序员工资高、待遇好&#xff0c; 2022 金九银十到了&#xff0c;你的小目标是 30K、40K&#xff0c;还是 16薪的 20K&#xff1f;作为一名 Java 开发工程师&#xff0c;当能力可以满足公司业务需求时&#xff0c;拿到超预期的 Offer 并不算难。然而&#xff0c;提升…

Java搭建实战毕设项目springboot停车位管理系统源码

大家好啊&#xff0c;我是测评君&#xff0c;欢迎来到web测评。 本期给大家带来一套Java开发的毕设项目springboot停车位管理系统源码&#xff0c;适合拿来做毕业设计的同学。可以下载来研究学习一下&#xff0c;本期把这套系统分享给大家。 技术架构 技术框架&#xff1a;jQu…

报表控件ActiveReports帮助高校实现办公、财务管理数字化

国内某知名高校教务处 陈主任&#xff1a; “我们教务处有十分多的文件、文档需要归纳整理&#xff0c;包括整个学校的文件通知公告、一些教务资源、职工工作日志记录、职工考勤记录等&#xff0c;同时还涉及一部分财务信息&#xff0c;职工的工资核算、学生续费的收纳等&…

初始python国度

print()函数 我里面有一个你可以直接使用的函数叫print()&#xff0c;可以将你想展示的东东在IDLE或标准的控制台上显示 print()函数可以输出哪些内容? (1)print()函数输出的内容可以是数字 (2)print()函数输出的内容可以是字符串 (3)print()函数输出的内容可以是含有运算符…