Qt数据库应用之通用数据库同步

目录
  • 一、前言
  • 二、功能特点
  • 三、体验地址
  • 四、效果图
  • 五、相关代码

一、前言

数据库同步的主要功能是将本地的数据库记录同步到远程的数据库,其中数据库类型不限,比如本地是sqlite数据库,远程可以是mysql数据库,本地是mysql数据库,远程也可以是postgresql数据库,只要数据库设置的时候设定好就行。这样做相当于就是通过程序的方式将数据库记录上传同步,还有一种机制是通过直接数据库上设置热备份啥的,个人还是习惯通过程序的方式,自主可控,比如可以自定义同步哪个表,哪部分数据需要同步。

有一种应用场景是现场很多客户端外接了各种传感器物联网设备(现在有个高大上的名字叫泛感知),客户端负责采集这些设备的数据,本地有记录,然后记录还可以同步到远程的数据库,需要提供一个app、网页、小程序啥的,去数据库中拿到对应的数据,如果没有这个上传到云端的过程,那就很难拿到这些数据,云端一般会有公网的IP地址,固定的,这样app也好小程序也好,直接发送请求回复对应的数据就行。除了能够拿到数据外,还可以发送对应的操作执行指令回控,比如单独一个表存储对应的指令,具体指令规则自定义,客户端在同步过程中还主动查询指令表是否有记录,有就取出来按照约定的规则执行,执行成功以后将对应记录删除。

数据库通信管理线程类特点:

  1. 可设置数据库类型,支持多种数据库类型。
  2. 数据库类型包括但不限于odbc、sqlite、mysql、postgresql、sqlserver、oracle、人大金仓等。
  3. 可设置数据库连接信息包括主机地址、用户信息等。
  4. 具有自动重连机制,可设置是否检查连接以及检查间隔。
  5. 支持单条sql语句队列,一般用于查询返回数据,每次插入一条执行一条。
  6. 支持多条sql语句队列,一般用于远程提交数据,每次插入一条执行多条。
  7. 支持批量sql语句队列,一般用于批量更新数据,每次插入多条执行多条。
  8. 可设置队列最大数量,限定排队处理的sql语句集合。
  9. 通过信号发出 打印信息、错误信息、查询结果。

Qt数据库相关应用开发总结

二、功能特点

  1. 同时支持多种数据库比如odbc、sqlite、mysql、postgresql、sqlserver、oracle、人大金仓等。
  2. 一个数据库类即可管理本地数据库通信,也支持远程数据库通信等。
  3. 数据库线程支持执行各种sql语句,包括单条和批量。
  4. 组件中的所有类打印信息、错误信息、执行结果都信号发出去。
  5. 集成数据库通用翻页类(负责具体处理逻辑),搭配分页导航控件(负责外观),形成超级牛逼的翻页控件。
  6. 集成数据库自动清理类,设定最大记录数后台自动清理早期数据。
  7. 集成自定义委托类,支持复选框、文本框、下拉框、日期框、微调框、进度条等。
  8. 同时支持Qt4-Qt6,亲测Qt4.6到Qt6.3任意版本,任意系统和编译器。
  9. 本组件无故障 360天7乘24小时 运行在至少上万个现场,商业级别品质保证。
  10. 每个类都对应完整详细的使用示例,注释详细,非常适合阅读学习。
  11. 可以作为独立的程序运行,比如自动清理早期数据,同步数据到云端。
  12. 全部线程处理,不卡界面,自动重连数据库。
  13. 普通测试情况,sqlite数据库,数据库发生器每秒钟插入1000条记录约0.003秒钟,同时自动清理数据类每秒钟删除1000条记录约0.13秒,不同线程互不干扰。

三、体验地址

体验地址:https://pan.baidu.com/s/15ZKAlptW-rDcNq8zlzdYLg  提取码:uyes 文件名:bin_dbtool.zip

国内站点:https://gitee.com/feiyangqingyun

国际站点:https://github.com/feiyangqingyun

四、效果图

五、相关代码

#include "frmdbupload.h"
#include "ui_frmdbupload.h"
#include "quihelper.h"
#include "dbconnthread.h"

frmDbUpload::frmDbUpload(QWidget *parent) : QWidget(parent), ui(new Ui::frmDbUpload)
{
    ui->setupUi(this);
    this->initForm();
    this->initConfig();
}

frmDbUpload::~frmDbUpload()
{
    delete ui;
}

void frmDbUpload::initForm()
{
    ui->frame->setFixedWidth(AppConfig::RightWidth);

    maxCount = 100;
    currentCount = 0;

    timer = new QTimer(this);
    timer->setInterval(1000);
    connect(timer, SIGNAL(timeout()), this, SLOT(on_btnDo_clicked()));

    //实例化数据库通信类
    dbConn = new DbConnThread(this);
    dbConn->setDbFlag("云端");
    connect(dbConn, SIGNAL(debug(QString)), this, SLOT(debug(QString)));
    connect(dbConn, SIGNAL(error(QString)), this, SLOT(error(QString)));
}

void frmDbUpload::initConfig()
{
    ui->cboxDbType->addItems(DbHelper::getDbType());
    ui->cboxDbType->setCurrentIndex(ui->cboxDbType->findText(AppConfig::DbType5));
    connect(ui->cboxDbType, SIGNAL(currentIndexChanged(int)), this, SLOT(saveConfig()));

    ui->txtDbName->setText(AppConfig::DbName5);
    connect(ui->txtDbName, SIGNAL(textChanged(QString)), this, SLOT(saveConfig()));

    ui->txtHostName->setText(AppConfig::HostName5);
    connect(ui->txtHostName, SIGNAL(textChanged(QString)), this, SLOT(saveConfig()));

    ui->txtHostPort->setText(QString::number(AppConfig::HostPort5));
    connect(ui->txtHostPort, SIGNAL(textChanged(QString)), this, SLOT(saveConfig()));

    ui->txtUserName->setText(AppConfig::UserName5);
    connect(ui->txtUserName, SIGNAL(textChanged(QString)), this, SLOT(saveConfig()));

    ui->txtUserPwd->setText(AppConfig::UserPwd5);
    connect(ui->txtUserPwd, SIGNAL(textChanged(QString)), this, SLOT(saveConfig()));
}

void frmDbUpload::saveConfig()
{
    AppConfig::DbType5 = ui->cboxDbType->currentText();
    AppConfig::DbName5 = ui->txtDbName->text();
    AppConfig::HostName5 = ui->txtHostName->text();
    AppConfig::HostPort5 = ui->txtHostPort->text().toInt();
    AppConfig::UserName5 = ui->txtUserName->text();
    AppConfig::UserPwd5 = ui->txtUserPwd->text();
    AppConfig::writeConfig();
}

void frmDbUpload::debug(const QString &msg)
{
    DbHelper::appendMsg(ui->txtMain, maxCount, currentCount, 0, msg);
}

void frmDbUpload::error(const QString &msg)
{
    DbHelper::appendMsg(ui->txtMain, maxCount, currentCount, 1, msg);
}

void frmDbUpload::on_btnOpen_clicked()
{
    if (ui->btnOpen->text() == "打开数据库") {
        DbInfo dbInfo;
        dbInfo.connName = this->objectName();
        dbInfo.dbName = AppConfig::DbName5;
        dbInfo.hostName = AppConfig::HostName5;
        dbInfo.hostPort = AppConfig::HostPort5;
        dbInfo.userName = AppConfig::UserName5;
        dbInfo.userPwd = AppConfig::UserPwd5;

        QString dbType = AppConfig::DbType5.toUpper();
        if (dbType == "SQLITE") {
            dbInfo.dbName = DbHelper::getDbDefaultFile();
        }

        dbConn->setConnInfo(DbHelper::getDbType(dbType), dbInfo);
        if (dbConn->openDb()) {
            dbConn->start();
            ui->btnOpen->setText("关闭数据库");
        } else {
            QString error = dbConn->getDatabase().lastError().text();
            QUIHelper::showMessageBoxError("打开数据库失败!\n" + error, 3);
        }
    } else {
        dbConn->stop();
        dbConn->closeDb();
        ui->btnOpen->setText("打开数据库");
        on_btnClear_clicked();
    }

    QTimer::singleShot(100, this, SLOT(on_btnInit_clicked()));
    QTimer::singleShot(1000, this, SLOT(on_btnStart_clicked()));
}

void frmDbUpload::on_btnCopy_clicked()
{
    //将数据库设置参数一键粘贴过来
    ui->cboxDbType->setCurrentIndex(ui->cboxDbType->findText(AppConfig::LocalDbType));
    ui->txtDbName->setText(AppConfig::LocalDbName);
    ui->txtHostName->setText(AppConfig::LocalHostName);
    ui->txtHostPort->setText(QString::number(AppConfig::LocalHostPort));
    ui->txtUserName->setText(AppConfig::LocalUserName);
    ui->txtUserPwd->setText(AppConfig::LocalUserPwd);
}

void frmDbUpload::on_btnInit_clicked()
{
    if (!dbConn->getOk()) {
        return;
    }

    //填充默认设备的初始数据
    QStringList sqls;
    //首先插入删除表语句
    sqls << "delete from NodeData";
    //再插入新建语句
    for (int i = 1; i < 10; i++) {
        QString sql1 = QString("insert into NodeData(PositionID,NodeValue,NodeStatus,SaveTime)");
        QString sql2 = QString("values('AT-1000%1','0',0,'%2')").arg(i).arg(DATETIME);
        sqls << (sql1 + " " + sql2);
    }

    dbConn->initDb(sqls);
}

void frmDbUpload::on_btnDo_clicked()
{
    if (!dbConn->getOk()) {
        return;
    }

    //在软件中相应的更新语句(增加/删除/修改)插入到队列
    //这里就举例更新值和时间
    for (int i = 1; i < 10; i++) {
        int value1 = rand() % 100;
        int value2 = rand() % 5;
        QString sql = QString("update NodeData set NodeValue='%1',NodeStatus='%2',SaveTime='%3' where PositionID='AT-1000%4'")
                      .arg(value1).arg(value2).arg(DATETIME).arg(i);
        dbConn->append(sql);
    }
}

void frmDbUpload::on_btnStart_clicked()
{
    if (ui->btnStart->text() == "启动服务") {
        on_btnDo_clicked();
        timer->start();
        ui->btnStart->setText("停止服务");
    } else {
        timer->stop();
        ui->btnStart->setText("启动服务");
    }
}

void frmDbUpload::on_btnClear_clicked()
{
    DbHelper::appendMsg(ui->txtMain, maxCount, currentCount, 0, "", true);
}

到此这篇关于Qt数据库应用之通用数据库同步的文章就介绍到这了,更多相关Qt通用数据库同步内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • Qt数据库应用之超级自定义委托

    目录 一.前言 二.功能特点 三.体验地址 四.效果图 五.相关代码 一.前言 在QTableView.QTreeView以及对于衍生的QTableWidget.QTreeWidget类中,需要用到自定义委托的情形很多,比如提供下拉框选择,进度条展示下载进度啥的,默认的单元格是没有这些效果的,需要自己单独用委托的形式来展示,自定义委托一般有两种UI形式,一种是单元格一直显示对应的委托控件比如复选框.按钮.进度条等,一种是用户鼠标按下才显示对应的委托控件,鼠标离开自动恢复原有单元格的形式. 在设计

  • Qt数据库应用之实现通用数据库清理

    目录 一.前言 二.功能特点 三.体验地址 四.效果图 五.相关代码 一.前言 很多项目如果需要存储很多日志记录比如运行日志,时间长了记录数量非常多,数据库体积不断增大,对应数据库表的增删改查的效率不断降低,为了消除这几个影响,需要有一套机制,不断将早期的数据清理,清理的规则比如可以指定表名.字段名.时间范围等. 日志记录的清理一方面是为了保证查询效率,毕竟数据量大了明显影响查询速度,一方面也是为了节约磁盘存储空间,毕竟存储空间有限,尤其是嵌入式板子,容量一般不会很大,记录无限制的存储下去会不断

  • Qt数据库应用之实现通用数据库分页

    目录 一.前言 二.功能特点 三.体验地址 四.效果图 五.相关代码 一.前言 数据库分页展示,在所有的涉及到数据库记录的项目中都是需要的,除了简单的设备信息表.用户信息表这种很少几条几十条数据量的表除外,其余的日志记录表等都需要分页展示数据,少量的数据可以滚动条下拉查看完,超过百条以上的一般建议要加上分页的功能处理,不然用户查看起来明显不舒服,体验不友好,最明显的例子就是网页的搜索结果,一次性展示上万条,不仅是多余的增加了查询的压力,而且用户往往只关注最前面的几页记录,再比如查询报警记录,一般

  • Qt数据库应用之实现数据图文混排

    目录 一.前言 二.功能特点 三.体验地址 四.效果图 五.相关代码 一.前言 除了能够打印基本的文字信息数据到pdf和纸张,越来越多的应用需求还要求能够导出图片,并且要支持图文混排,相当于doc文档类似,当然也不会是太复杂的,类似于打印报表一样,有表格形式的文字描述,也有对应的图片插入其中,图文混排的应用场景还真不少比如医疗行业输出诊断结果往往都带了图片.于是针对这个需求特意开辟了新的类DataCreat专门生成报表的数据,将生成好的数据体直接传入给DataPrint类即可,如果有各种各样的不

  • Qt数据库应用之实现数据打印到纸张

    目录 一.前言 二.功能特点 三.体验地址 四.效果图 五.相关代码 一.前言 数据能够打印到pdf文件,当然可以打印到纸张,而且使用qprinter默认就是打印到纸张的,上一篇文章写得功能是打印到pdf,其实还要单独特殊设置打印到文件,并指定格式为pdf.不指定输出文件和格式默认就是打印到纸张,关于Qt打印内容到纸张,网上的办法非常多,比如有些直接用painter绘制,逐步控制分页打印,个人还是喜欢html格式的内容传入,因为html格式相当灵活,可控范围相当大,而且整齐,甚至可以先直接输出到

  • Qt数据库相关应用开发总结

    目录 一.前言 二.数据库开发经验总结 三.数据库连接说明 四.数据库操作流程代码 五.数据库综合应用组件 一.前言 近期花了两个多月时间,将数据库相关的代码重新封装成了各种轮子(这条路必须打通,打通以后,相关项目只需要引入这个组件pri即可),测试了从Qt4.7到Qt6.1的各种版本,测试了odbc.sqlite.mysql.postgresql.sqlserver.oracle.人大金仓等数据库,测试了本地连接.远程连接.阿里云连接等,测试了windows.linux.mac等系统,将所有项

  • Qt数据库应用之数据打印到pdf

    目录 一.前言 二.功能特点 三.体验地址 四.效果图 五.相关代码 一.前言 自从数据可以导出到xls,又有客户提出了不同的需求,比如既然可以将数据导出到xls,那是否可以导出到pdf文件呢?因为xls打开以后用户可以修改数据造假之类的,而pdf默认是不可编辑的,除非借助专业的工具,所以如果想要限定用户导出数据不能被更改,那导出pdf是最佳选择.写程序往往都是这样,一步步慢慢增加,随着用户需求的增加,程序量也越来越多,轮子组件也越来越多.往往客户提需求的时候,一定要认真聆听,尤其是一线用户,实

  • Qt数据库应用之实现通用数据生成器

    目录 一.前言 二.功能特点 三.体验地址 四.效果图 五.相关代码 一.前言 有两种应用场景需要用到数据生成器,一种是需要测试数据库性能,比如在100万条和1000万条记录的时候对比查询或更新语句执行耗时,一种是随机模拟生成一堆数据,用来测试程序的性能,看下程序中到了百万千万级别的数据量的时候,程序的代码执行是否受影响,影响有大等.很多人觉得sqlite数据库性能超过几十万就不行,于是亲自用这个数据发生器随机模拟生成了一亿条记录,测试下来发现性能有损失,但是不像传说中的垃圾,起码还是完全可用的

  • Qt数据库应用之通用数据库同步

    目录 一.前言 二.功能特点 三.体验地址 四.效果图 五.相关代码 一.前言 数据库同步的主要功能是将本地的数据库记录同步到远程的数据库,其中数据库类型不限,比如本地是sqlite数据库,远程可以是mysql数据库,本地是mysql数据库,远程也可以是postgresql数据库,只要数据库设置的时候设定好就行.这样做相当于就是通过程序的方式将数据库记录上传同步,还有一种机制是通过直接数据库上设置热备份啥的,个人还是习惯通过程序的方式,自主可控,比如可以自定义同步哪个表,哪部分数据需要同步. 有

  • Qt数据库应用之实现通用数据库采集

    目录 一.前言 二.功能特点 三.体验地址 四.效果图 五.相关代码 一.前言 数据库采集对应的就是上一篇文章的数据库同步,数据库同步到云端数据库以后,app.网页.小程序啥的要数据的话,可以通过执行http请求拿到数据,http接收应答这边程序一般最简单可以用php写,几行代码即可,比如根据请求的参数构建需要执行的sql语句,执行以后将结果json形式返回即可. 通过Qt程序去做数据库采集有多种方式,即可直接连接数据库然后绑定数据库表到QSqlTableModel,然后不断调用select方法

  • Qt数据库应用之实现通用数据库请求

    目录 一.前言 二.功能特点 三.体验地址 四.效果图 五.相关代码 一.前言 数据库请求是在数据库采集的基础上,换成http请求的形式来获取数据,这样就脱离了数据库组件,而采用的通用的http请求的形式从数据库拿数据库,这个通用性就非常广泛了,比如对方用java采集到设备的数据存入数据库,另外一个区域是用的c#采集的数据入库,然后统一规则统一规范约定一个请求机制,定时器或者线程取执行请求,拿到的json数据,挨个取出来结果,数组集合的方式发信号出去. 之前写过的可视化大屏电子看板程序,采用的也

  • ASP.NET对SQLServer的通用数据库访问类

    本文模仿实现数据库访问的通用类,代码清晰,而且很实用,包括了对数据库的所有的常用的操作. /// <summary> /// 数据库访问通用类 /// </summary> public class SqlHelper { private string connectionString; /// <summary> /// 设定数据库访问字符串 /// </summary> public string ConnectionString { set { con

  • 初识通用数据库操作类——前端easyui-datagrid,form(php)

    初识通用数据库操作类--前端easyui-datagrid,form(php),实现代码比较简单,具体实现步骤请看下文. 实现功能: 左端datagrid显示简略信息,右侧显示选中行详细信息,数据库增删改 (1)点击选中行,右侧显示详细信息,其中[新增].[修改].[删除]按钮可用,[保存]按钮禁用 (2)点击[新增]按钮,[修改],[删除]按钮禁用,[保存]按钮启用 (3)点击[修改]按钮,[新增],[删除]按钮禁用 难点:通用数据库操作类中insert方法跟update方法 最终效果图: 前

  • ADO.NET通用数据库访问类

    本文实例为大家分享了ADO.NET通用数据库访问类,供大家参考学习,具体内容如下 using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Data; using System.Data.SqlClient; namespace Test { public class DBHelper { publ

  • SQL Server中通用数据库角色权限的处理详解

    前言 安全性是所有数据库管理系统的一个重要特征.理解安全性问题是理解数据库管理系统安全性机制的前提. 最近和同事在做数据库权限清理的事情,主要是删除一些账号:取消一些账号的较大的权限等,例如,有一些有db_owner权限,我们取消账号的数据库角色db_owner,授予最低要求的相关权限.但是这种工作完全是一个体力活,而且是吃力不讨好,而且推进很慢.另外,为了管理方便和细化,我们又在常用的数据库角色外,新增了6个通用的数据库角色. 如下截图所示. 另外,为了减少授权工作量和一些重复的体力活,我们创

  • 一款免费开源的通用数据库工具DBeaver

    在制作<SQL 入门教程>时,接触到了这款非常强大易用的数据库管理和开发工具:DBeaver,也就是上面这个可爱的小河狸. DBeaver 是一个基于 Java 开发,免费开源的通用数据库管理和开发工具,使用非常友好的 ASL协议.可以通过官方网站或者 Github进行下载. 由于 DBeaver 基于 Java 开发,可以运行在各种操作系统上,包括:Windows.Linux.macOS 等.DBeaver 采用 Eclipse 框架开发,支持插件扩展,并且提供了许多数据库管理工具:ER 图

随机推荐