更多精彩内容 |
---|
个人内容分类汇总 |
数据库开发 |
- 这是通过学习Qt官方Demo产生的一个示例;
- 通过自己理解加入了一些更加详细便于学习的内容;
- 添加了非常详细的注释信息,对于小白更加友好。
开发环境说明
- 通过QSqlTableModel将数据库内容直接显示到QTableView中,直观的显示和修改数据库中的数据;
- 程序启动时自动创建一个数据库,并创建一个表写入默认测试数据,可选择创建文件数据库还是内存数据库;
- 写入测试数据时演示了QSqlQuery的五种不同的插入数据方式;
- 在界面上修改内容后不会立即保存到数据库中,需要点击提交按键才一次性将所有修改的内容保存到数据库;
- 如果在界面上修改了内容,还没有提交事务时可以选择还原所有修改内容。
实现效果如下:
啥也不说了,直接上代码,一切有注释
pro文件: Qt使用到数据库,上来什么都别管,先在pro文件添加上QT += sql
;
main.cpp文件:程序第一次启动时在main函数中创建数据库并写入数据;
#include "widget.h"
#include
#include
#include
#include
/**
* @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
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
#include
#include
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();
}