Qt-数据库开发-通过QSqlTableModel显示和修改数据,开启事务
更多精彩内容 |
---|
????个人内容分类汇总 ???? |
????数据库开发 ???? |
1、概述
- 这是通过学习Qt官方Demo产生的一个示例;
- 通过自己理解加入了一些更加详细便于学习的内容;
- 添加了非常详细的注释信息,对于小白更加友好。
开发环境说明
- 系统:Windows10、Ubuntu20.04
- Qt版本:V5.12.5
- 编译器:MSVC2017-64、GCC/G++64
2、实现效果
- 通过QSqlTableModel将数据库内容直接显示到QTableView中,直观的显示和修改数据库中的数据;
- 程序启动时自动创建一个数据库,并创建一个表写入默认测试数据,可选择创建文件数据库还是内存数据库;
- 写入测试数据时演示了QSqlQuery的五种不同的插入数据方式;
- 在界面上修改内容后不会立即保存到数据库中,需要点击提交按键才一次性将所有修改的内容保存到数据库;
- 如果在界面上修改了内容,还没有提交事务时可以选择还原所有修改内容。
-
实现效果如下:
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(); }