Qt缓存数据库数据表示例:缓存对数据库的修改,手动提交保存更改:model->setEditStrategy(QSqlTableModel::OnManualSubmit)

缓存表示例界面:

展示了如何使用表视图来访问数据库,缓存对数据的任何更改,直到用户使用按钮明确提交这些更改
Qt缓存数据库数据表示例:缓存对数据库的修改,手动提交保存更改:model->setEditStrategy(QSqlTableModel::OnManualSubmit)_第1张图片
该示例由一个类TableEditor组成,TableEditor是一个自定义对话框小部件,允许用户修改存储在数据库中的数据

TableEditor类定义

  • TableEditor类继承了QWidget,作为主窗口
class TableEditor : public QWidget
{
    Q_OBJECT

public:
    explicit TableEditor(const QString &tableName, QWidget *parent = nullptr);

private slots:
    void submit();

private:
    QPushButton *submitButton;
    QPushButton *revertButton;
    QPushButton *quitButton;
    QDialogButtonBox *buttonBox;
    QSqlTableModel *model;
};

TableEditor构造函数接受两个参数:第一个是对TableEditor对象将操作的数据库表的引用。另一个是指向父小部件的指针,并被传递给基类构造函数
QSqlTableModel类可用于向视图类(如QTableView)提供数据。QSqlTableModel类提供了一个可编辑的数据模型,使得从单个表中读写数据库记录成为可能。它建立在较低级别的SqlQuery类之上,该类提供了执行和操作SQL语句的方法。
另外还展示如何使用表视图来缓存对数据的任何更改,直到明确请求提交它们。为此,我们需要在模型和编辑器按钮之外声明一个submit()槽函数

  • main函数主要代码
int main(int argc, char *argv[])
{
    QApplication app(argc, argv);
    if (!createConnection())
        return 1;

    TableEditor editor("person");
    editor.show();
    return app.exec();
}
  • createConnection()函数定义在connection.h的头文件中,此函数创建内存临时数据库,建立三个数据表,并添加一些记录
static bool createConnection()
{
    QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE");
    db.setDatabaseName(":memory:");
    if (!db.open()) {
        QMessageBox::critical(nullptr, QObject::tr("Cannot open database"),
            QObject::tr("Unable to establish a database connection.\n"
                        "This example needs SQLite support. Please read "
                        "the Qt SQL driver documentation for information how "
                        "to build it.\n\n"
                        "Click Cancel to exit."), QMessageBox::Cancel);
        return false;
    }

    QSqlQuery query;
    query.exec("create table person (id int primary key, "
               "firstname varchar(20), lastname varchar(20))");
    query.exec("insert into person values(101, 'Danny', 'Young')");
    query.exec("insert into person values(102, 'Christine', 'Holand')");
    query.exec("insert into person values(103, 'Lars', 'Gordon')");
    query.exec("insert into person values(104, 'Roberto', 'Robitaille')");
    query.exec("insert into person values(105, 'Maria', 'Papadopoulos')");

    query.exec("create table items (id int primary key,"
                                             "imagefile int,"
                                             "itemtype varchar(20),"
                                             "description varchar(100))");
    query.exec("insert into items "
               "values(0, 0, 'Qt',"
               "'Qt is a full development framework with tools designed to "
               "streamline the creation of stunning applications and  "
               "amazing user interfaces for desktop, embedded and mobile "
               "platforms.')");
    query.exec("insert into items "
               "values(1, 1, 'Qt Quick',"
               "'Qt Quick is a collection of techniques designed to help "
               "developers create intuitive, modern-looking, and fluid "
               "user interfaces using a CSS & JavaScript like language.')");
    query.exec("insert into items "
               "values(2, 2, 'Qt Creator',"
               "'Qt Creator is a powerful cross-platform integrated "
               "development environment (IDE), including UI design tools "
               "and on-device debugging.')");
    query.exec("insert into items "
               "values(3, 3, 'Qt Project',"
               "'The Qt Project governs the open source development of Qt, "
               "allowing anyone wanting to contribute to join the effort "
               "through a meritocratic structure of approvers and "
               "maintainers.')");

    query.exec("create table images (itemid int, file varchar(20))");
    query.exec("insert into images values(0, 'images/qt-logo.png')");
    query.exec("insert into images values(1, 'images/qt-quick.png')");
    query.exec("insert into images values(2, 'images/qt-creator.png')");
    query.exec("insert into images values(3, 'images/qt-project.png')");

    return true;
}
  • TableEditor类的实现
    类实现只包含两个函数,构造函数和submit()槽,在构造函数中,创建并定制数据模型和各种窗口小部件
TableEditor::TableEditor(const QString &tableName, QWidget *parent)
    : QWidget(parent)
{
    model = new QSqlTableModel(this);
    model->setTable(tableName);
    model->setEditStrategy(QSqlTableModel::OnManualSubmit);
    model->select();

    model->setHeaderData(0, Qt::Horizontal, tr("ID"));
    model->setHeaderData(1, Qt::Horizontal, tr("First name"));
    model->setHeaderData(2, Qt::Horizontal, tr("Last name"));

首先,我们创建数据模型,并设置希望模型运行的SQL数据库表。QSqlTableModel::setable()函数不会从表中选择数据,它只获取它的字段信息,稍后调用QSqlTableModel::select()函数,用表中的数据填充模型,可以通过指定过滤器和排序条件来定制选择
我们还设置了模型的编辑策略,编辑策略规定了用户在视图中所做的更改实际应用于数据库的时间,我们希望在表视图(即模型)中缓存更改,直到用户显式提交它们,因此我们选择了QSqlTableModel::OnManualSubmit策略,另外还有:

QSqlTableModel::OnFieldChange
QSqlTableModel::OnRowChange

最后,我们使用模型从QSqlQueryModel类继承的setHeaderData()函数设置视图标题中显示的标签

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

然后我们创建一个表视图view,QTableView类提供了表视图的默认模型/视图实现,它实现了一个显示模型的表视图,它还允许用户编辑项目,将更改存储在模型中,若要创建只读视图,请使用从QAbstractItemView类继承的视图的editTriggers属性设置适当的标志

submitButton = new QPushButton(tr("Submit"));
submitButton->setDefault(true);
revertButton = new QPushButton(tr("&Revert"));
quitButton = new QPushButton(tr("Quit"));

buttonBox = new QDialogButtonBox(Qt::Vertical);
buttonBox->addButton(submitButton, QDialogButtonBox::ActionRole);
buttonBox->addButton(revertButton, QDialogButtonBox::ActionRole);
buttonBox->addButton(quitButton, QDialogButtonBox::RejectRole);

TableEditor中的三个按钮是常规的buttons对象,我们将它们添加到按钮框中,以确保按钮以适合当前小部件样式的布局呈现,QDialogButtonBox允许开发人员向其中添加按钮,并将自动为用户的桌面环境使用适当的布局
对话框的大多数按钮遵循特定的角色,使用addButton()函数向按钮框添加按钮时,必须使用QDialogButtonBox::ButtonRole枚举指定按钮的角色,或者QDialogButtonBox提供了几个您可以使用的标准按钮(例如,确定、取消、保存),它们作为标志存在,因此您可以在构造函数中对它们进行OR运算

    connect(submitButton, &QPushButton::clicked, this, &TableEditor::submit);
    connect(revertButton, &QPushButton::clicked,  model, &QSqlTableModel::revertAll);
    connect(quitButton, &QPushButton::clicked, this, &TableEditor::close);

我们将“退出”按钮连接到表格编辑器的close()插槽,将“提交”按钮连接到我们的私有Submit()插槽。后一个插槽将负责数据事务。最后,我们将“恢复”按钮连接到模型的revertAll()插槽,恢复所有挂起的更改(即恢复原始数据)

    QHBoxLayout *mainLayout = new QHBoxLayout;
    mainLayout->addWidget(view);
    mainLayout->addWidget(buttonBox);
    setLayout(mainLayout);

    setWindowTitle(tr("Cached Table"));
}

最后,我们将按钮框和表格视图添加到布局中,在主窗口上安装布局,并设置主窗口的标题

void TableEditor::submit()
{
    model->database().transaction();
    if (model->submitAll()) {
        model->database().commit();
    } else {
        model->database().rollback();
        QMessageBox::warning(this, tr("Cached Table"),
                             tr("The database reported an error: %1")
                             .arg(model->lastError().text()));
    }
}

每当用户点击“提交”按钮保存他们的更改时,就会调用submit()槽
首先,我们使用QSqlDatabase::transaction()函数在数据库上开始一个事务。数据库事务是与数据库管理系统或类似系统交互的一个单元,以一种连贯可靠的方式独立于其他事务进行处理。可以使用QSqlTableModel::database()函数获得指向已用数据库的指针
然后,我们尝试提交所有待定的更改,如果没有出现错误,我们就使用SqlDatabase::commit()函数将事务提交给数据库。否则,我们使用QSqlDatabase::rollback()函数执行事务的回滚,并向用户发出警告

完整代码

  • 完整main.cpp文件代码
#include 

#include "connection.h"
#include "tableeditor.h"

//! [0]
int main(int argc, char *argv[])
{
    QApplication app(argc, argv);
    if (!createConnection())
        return 1;

    TableEditor editor("person");
    editor.show();
    return app.exec();
}
//! [0]
  • 完整tableeditor.h头文件
#ifndef TABLEEDITOR_H
#define TABLEEDITOR_H

#include 

QT_BEGIN_NAMESPACE
class QDialogButtonBox;
class QPushButton;
class QSqlTableModel;
QT_END_NAMESPACE

//! [0]
class TableEditor : public QWidget
{
    Q_OBJECT

public:
    explicit TableEditor(const QString &tableName, QWidget *parent = nullptr);

private slots:
    void submit();

private:
    QPushButton *submitButton;
    QPushButton *revertButton;
    QPushButton *quitButton;
    QDialogButtonBox *buttonBox;
    QSqlTableModel *model;
};
//! [0]

#endif
  • 完整tableeditor.cpp源文件
#include 
#include 

#include "tableeditor.h"

//! [0]
TableEditor::TableEditor(const QString &tableName, QWidget *parent)
    : QWidget(parent)
{
    model = new QSqlTableModel(this);
    model->setTable(tableName);
    model->setEditStrategy(QSqlTableModel::OnManualSubmit);
    model->select();

    model->setHeaderData(0, Qt::Horizontal, tr("ID"));
    model->setHeaderData(1, Qt::Horizontal, tr("First name"));
    model->setHeaderData(2, Qt::Horizontal, tr("Last name"));

//! [0] //! [1]
    QTableView *view = new QTableView;
    view->setModel(model);
    view->resizeColumnsToContents();
//! [1]

//! [2]
    submitButton = new QPushButton(tr("Submit"));
    submitButton->setDefault(true);
    revertButton = new QPushButton(tr("&Revert"));
    quitButton = new QPushButton(tr("Quit"));

    buttonBox = new QDialogButtonBox(Qt::Vertical);
    buttonBox->addButton(submitButton, QDialogButtonBox::ActionRole);
    buttonBox->addButton(revertButton, QDialogButtonBox::ActionRole);
    buttonBox->addButton(quitButton, QDialogButtonBox::RejectRole);
//! [2]

//! [3]
    connect(submitButton, &QPushButton::clicked, this, &TableEditor::submit);
    connect(revertButton, &QPushButton::clicked,  model, &QSqlTableModel::revertAll);
    connect(quitButton, &QPushButton::clicked, this, &TableEditor::close);
//! [3]

//! [4]
    QHBoxLayout *mainLayout = new QHBoxLayout;
    mainLayout->addWidget(view);
    mainLayout->addWidget(buttonBox);
    setLayout(mainLayout);

    setWindowTitle(tr("Cached Table"));
}
//! [4]

//! [5]
void TableEditor::submit()
{
    model->database().transaction();
    if (model->submitAll()) {
        model->database().commit();
    } else {
        model->database().rollback();
        QMessageBox::warning(this, tr("Cached Table"),
                             tr("The database reported an error: %1")
                             .arg(model->lastError().text()));
    }
}
//! [5]
  • 完整数据库connection.h连接文件
#ifndef CONNECTION_H
#define CONNECTION_H

#include 
#include 
#include 
#include 

/*
    This file defines a helper function to open a connection to an
    in-memory SQLITE database and to create a test table.

    If you want to use another database, simply modify the code
    below. All the examples in this directory use this function to
    connect to a database.
*/
//! [0]
static bool createConnection()
{
    QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE");
    db.setDatabaseName(":memory:");
    if (!db.open()) {
        QMessageBox::critical(nullptr, QObject::tr("Cannot open database"),
            QObject::tr("Unable to establish a database connection.\n"
                        "This example needs SQLite support. Please read "
                        "the Qt SQL driver documentation for information how "
                        "to build it.\n\n"
                        "Click Cancel to exit."), QMessageBox::Cancel);
        return false;
    }

    QSqlQuery query;
    query.exec("create table person (id int primary key, "
               "firstname varchar(20), lastname varchar(20))");
    query.exec("insert into person values(101, 'Danny', 'Young')");
    query.exec("insert into person values(102, 'Christine', 'Holand')");
    query.exec("insert into person values(103, 'Lars', 'Gordon')");
    query.exec("insert into person values(104, 'Roberto', 'Robitaille')");
    query.exec("insert into person values(105, 'Maria', 'Papadopoulos')");

    query.exec("create table items (id int primary key,"
                                             "imagefile int,"
                                             "itemtype varchar(20),"
                                             "description varchar(100))");
    query.exec("insert into items "
               "values(0, 0, 'Qt',"
               "'Qt is a full development framework with tools designed to "
               "streamline the creation of stunning applications and  "
               "amazing user interfaces for desktop, embedded and mobile "
               "platforms.')");
    query.exec("insert into items "
               "values(1, 1, 'Qt Quick',"
               "'Qt Quick is a collection of techniques designed to help "
               "developers create intuitive, modern-looking, and fluid "
               "user interfaces using a CSS & JavaScript like language.')");
    query.exec("insert into items "
               "values(2, 2, 'Qt Creator',"
               "'Qt Creator is a powerful cross-platform integrated "
               "development environment (IDE), including UI design tools "
               "and on-device debugging.')");
    query.exec("insert into items "
               "values(3, 3, 'Qt Project',"
               "'The Qt Project governs the open source development of Qt, "
               "allowing anyone wanting to contribute to join the effort "
               "through a meritocratic structure of approvers and "
               "maintainers.')");

    query.exec("create table images (itemid int, file varchar(20))");
    query.exec("insert into images values(0, 'images/qt-logo.png')");
    query.exec("insert into images values(1, 'images/qt-quick.png')");
    query.exec("insert into images values(2, 'images/qt-creator.png')");
    query.exec("insert into images values(3, 'images/qt-project.png')");

    return true;
}
//! [0]

#endif

你可能感兴趣的:(C++,与,Qt5,qt,缓存,big,data)