• 2781阅读
  • 19回复

Qt数据库集成应用封装 [复制链接]

上一主题 下一主题
在线liudianwu
 

平时的大大小小的项目中,基本上都需要与数据打交道,会遇到各种各样的应用场景,本人主要遇到四种场景
1:数据库自动重连,例如mysql数据库中经常遇到服务器挂掉的情况,需要自动检测并重新连接数据库。
2:数据库自动清理早期数据,保证数据库中为最新的数据,而容量有限。
3:数据实时同步云端,客户端从云端同步数据到本地。
4:多线程批量执行sql语句。
为此,特意将各种应用场景封装成类,每个项目只需要传入对应参数即可。大大节省了开发时间。集成到pri文件中,每次项目引入即可。

DbTcpClientThread
/**
* 远程数据实时同步线程客户端,负责上传数据
* 1:可设置远程mysql数据库信息
* 2:自动重连数据库
* 3:可设置检测连接间隔
* 4:自动重置远程设备信息
* 5:所有消息都发送信号,可在信号槽函数中打印输出
*/

DbTcpServerThread
/**
* 远程数据实时同步线程服务端,负责下载数据
* 1:可设置远程mysql数据库信息
* 2:自动重连数据库
* 3:可设置检测连接间隔
* 4:可设置要查询的表名
* 5:所有消息都发送信号,可在信号槽函数中打印输出
* 6:返回数据结果严格按照字段顺序
* 7:返回的数据同时包含关键字字段数据
* 8:提供接口可对远程数据库执行sql语句
* 9:提供接口可对远程数据库获取对应表数据
*/

DbTcpDataThread
/**
* 本地数据同步到远程数据库线程
* 1:可设置远程mysql数据库信息
* 2:可设置本地mysql数据库信息
* 3:自动重连数据库,包括本地数据库和远程数据库
* 4:可设置检测连接间隔
* 5:所有消息都发送信号,可在信号槽函数中打印输出
* 6:支持优先执行sql语句
*/

DbWebServerThread
/**
* 远程数据实时同步线程服务端,负责下载数据
* 1:通过web方式访问网页获取返回值
* 2:可以拓展支持更多种支持方式
* 3:可设置检测连接间隔
* 4:可设置要查询的表名
* 5:所有消息都发送信号,可在信号槽函数中打印输出
* 6:返回数据结果严格按照字段顺序
* 7:返回的数据同时包含关键字字段数据
*/

DbCountThread
/**
* 数据库通用翻页类
* 1:自动按照设定的每页多少行数据分页
* 2:只需要传入表名/字段集合/每页行数/翻页指示按钮/文字指示标签
* 3:提供公共静态方法绑定字段数据到下拉框
* 4:建议条件字段用数字类型的主键,速度极快
* 5:增加线程查询符合条件的记录总数,数据量巨大时候不会卡主界面
*/

DbLocalThread
/**
* 本地数据库打开、关闭、检查、重连
* 1:支持数据库自动重连
* 2:可设置检查数据库时间间隔
*/

DbExecSqlThread
/**
* 批量执行sql语句线程类
* 1:可设置对应数据库连接名称和sql语句
* 2:执行结果提供信号传出执行是否成功,执行条数,用时
*/

DbDelegate
/**
* 自定义委托类
* 1:可设置多种委托类型,例如文本框/下拉框/日期框等
* 2:可设置文本框是否密文显示
* 3:可设置默认数据,包括下拉框数据集合
* 4:提供值变化信号,比方说下拉框值改动触发
*/

DbCleanThread
/**
* 自动清理数据类
* 1:可设置要清理的对应数据库连接名称和表名
* 2:可设置条件字段
* 3:可设置排序字段
* 4:可设置最大保留的记录数
* 5:可设置执行自动清理的间隔
* 6:后期支持多个数据库和多个表
* 7:建议条件字段用数字类型的主键,速度极快
* 8:增加统计用字段名称设置
*/





在线liudianwu

只看该作者 1楼 发表于: 06-11



离线liuchangyin

只看该作者 2楼 发表于: 06-12
离线jsxyhyj

只看该作者 3楼 发表于: 06-13
相当不错
在线九重水

只看该作者 4楼 发表于: 06-13
数据库程序设计现在好像很吃香啊。什么大数据啊,云啊,
离线stlcours

只看该作者 5楼 发表于: 06-13
是开源还是卖钱?话说DbDelegate类有必要吗?客户可以自己设置啊。设置代理反而不灵活了。
离线pangwei

只看该作者 6楼 发表于: 06-14
http://www.qtdebug.com/qtbook-db-util/这个数据库操作的类也还可以
在线liudianwu

只看该作者 7楼 发表于: 06-14
回 pangwei 的帖子
pangwei:http://www.qtdebug.com/qtbook-db-util/这个数据库操作的类也还可以 (2017-06-14 08:38) 

公孙二狗现在搞java开发去了!
离线liuyuanan

只看该作者 8楼 发表于: 06-18
多节点数据存储及同步,建议使用Redis
离线lin617559770

只看该作者 9楼 发表于: 06-21
楼主你这个demo开源吗
离线apud

只看该作者 10楼 发表于: 07-13
楼主,一两年前我陆陆续续花了一两百块买过你几个源码,实在经典,学到不少东西。现有一个问题特来请教:使用qt连接阿里云的数据库,软件闲置几分钟再次操作数据库,显示mysql has gone away。这应该怎么解决,按照网上办法修改my.ini配置依然无效。软件要求效率高,所以不可能需要用到数据库操作时再次重连。也就是我希望它能长时间保持和数据库连接。
在线liudianwu

只看该作者 11楼 发表于: 07-14
回 apud 的帖子
apud:
楼主,一两年前我陆陆续续花了一两百块买过你几个源码,实在经典,学到不少东西。现有一个问题特来请教:使用qt连接阿里云的数据库,软件闲置几分钟再次操作数据库,显示mysql has gone away。这应该怎么解决,按照网上办法修改my.ini配置依然无效。软件要求效率高,所以不可能需要用到数据库操作时再次重连。也就是我希望它能长时间保持和数据库连接。

这个问题是mysql数据库的经典问题,貌似开源版本的就是存在这个问题,目前我们的水平很难从源码层更改mysql,只能定时判断数据库连接,然后一旦发现执行失败超过次数则说明数据库断开了连接,这样就重新连接数据库即可!
核心代码如下
  1. #include "dblocalthread.h"
  2. DbLocalThread *DbLocalThread::self = 0;
  3. DbLocalThread::DbLocalThread(QObject *parent) : QThread(parent)
  4. {
  5.     stopped = false;
  6.     dbOkLocal = false;
  7.     lastCheckTimeLocal = QDateTime::currentDateTime();
  8.     checkInterval = 30;
  9.     dbTypeLocal = DbType_MySql;
  10.     connNameLocal = "qt_sql_default_connection";
  11.     hostNameLocal = "127.0.0.1";
  12.     portLocal = 3306;
  13.     dbNameLocal = "tcms_liu_mysql";
  14.     userNameLocal = "root";
  15.     userPwdLocal = "root";    
  16. }
  17. void DbLocalThread::run()
  18. {
  19.     while (!stopped) {
  20.         //定时执行一次校验数据库连接是否正常
  21.         QDateTime now = QDateTime::currentDateTime();
  22.         if (lastCheckTimeLocal.secsTo(now) >= checkInterval) {
  23.             checkDb();
  24.             lastCheckTimeLocal = now;
  25.             continue;
  26.         }
  27.         //如果数据库连接正常则处理数据,不正常则重连数据库
  28.         if (!dbOkLocal) {
  29.             openDb();
  30.             emit debug(QString("重连数据库%1").arg(dbOkLocal ? "成功" : "失败"));
  31.             msleep(3000);
  32.         } else {
  33.             msleep(1000);
  34.         }
  35.     }
  36.     stopped = false;
  37. }
  38. bool DbLocalThread::openDb()
  39. {
  40.     //可以自行增加其他数据库的支持
  41.     if (dbTypeLocal == DbType_Sqlite) {
  42.         dbConnLocal = QSqlDatabase::addDatabase("QSQLITE", connNameLocal);
  43.         dbConnLocal.setDatabaseName(dbNameLocal);
  44.     } else if (dbTypeLocal == DbType_MySql) {
  45.         dbConnLocal = QSqlDatabase::addDatabase("QMYSQL", connNameLocal);
  46.         dbConnLocal.setHostName(hostNameLocal);
  47.         dbConnLocal.setPort(portLocal);
  48.         dbConnLocal.setDatabaseName(dbNameLocal);
  49.         dbConnLocal.setUserName(userNameLocal);
  50.         dbConnLocal.setPassword(userPwdLocal);
  51.     }
  52.     dbOkLocal = dbConnLocal.open();
  53.     return dbOkLocal;
  54. }
  55. bool DbLocalThread::checkDb()
  56. {
  57.     QDateTime dtStart = QDateTime::currentDateTime();
  58.     QString sql = "select 1";
  59.     QSqlQuery query(dbConnLocal);
  60.     dbOkLocal = query.exec(sql);
  61.     QDateTime dtEnd = QDateTime::currentDateTime();
  62.     double ms = dtStart.msecsTo(dtEnd);
  63.     emit debug(QString("检查数据库连接(共 %1 条/用时 %2 秒)").arg(1).arg(QString::number(ms / 1000, 'f', 3)));
  64.     return dbOkLocal;
  65. }
  66. void DbLocalThread::closeDb()
  67. {
  68.     dbConnLocal.close();
  69.     QSqlDatabase::removeDatabase(connNameLocal);
  70.     dbOkLocal = false;
  71.     emit debug("关闭数据库");
  72. }
  73. void DbLocalThread::stop()
  74. {
  75.     stopped = true;
  76. }
  77. void DbLocalThread::setConnInfo(DbLocalThread::DbType dbType, const QString &connName, const QString &hostName, int port, const QString &dbName, const QString &userName, const QString &userPwd)
  78. {
  79.     this->dbTypeLocal = dbType;
  80.     this->connNameLocal = connName;
  81.     this->hostNameLocal = hostName;
  82.     this->portLocal = port;
  83.     this->dbNameLocal = dbName;
  84.     this->userNameLocal = userName;
  85.     this->userPwdLocal = userPwd;
  86. }
  87. void DbLocalThread::setCheckInterval(int checkInterval)
  88. {
  89.     if (checkInterval > 5 && this->checkInterval != checkInterval) {
  90.         this->checkInterval = checkInterval;
  91.     }
  92. }

离线apud

只看该作者 12楼 发表于: 07-14
非常感谢,我学习下。我记得之前使用阿里云的另一个套餐的数据库并没有这个问题。换了ECS服务器,自己windows server 2008装了个数据库就存在这个问题。如果用这个方法重连的话,是否对效率有影响。
在线liudianwu

只看该作者 13楼 发表于: 07-14
回 apud 的帖子
apud:非常感谢,我学习下。我记得之前使用阿里云的另一个套餐的数据库并没有这个问题。换了ECS服务器,自己windows server 2008装了个数据库就存在这个问题。如果用这个方法重连的话,是否对效率有影响。 (2017-07-14 20:32) 

完全没有影响,因为是多线程,丝毫不会内存泄漏!Qt对数据库的封装还是非常完美的,采用了连接名称作为处理标识符。
离线apud

只看该作者 14楼 发表于: 07-15
OK。顺便问一下。你这源码可以购买吗?
我挺感兴趣的,想支持一下大神。
建议你可以开一个淘宝店,这样购买源码也方便点。
离线apud

只看该作者 15楼 发表于: 07-25
回 liudianwu 的帖子
liudianwu:这个问题是mysql数据库的经典问题,貌似开源版本的就是存在这个问题,目前我们的水平很难从源码层更改mysql,只能定时判断数据库连接,然后一旦发现执行失败超过次数则说明数据库断开了连接,这样就重新连接数据库即可!
核心代码如下#include "dblocalthread.h"
DbL .. (2017-07-14 08:29) 

用这种方法遇到的一个问题,程序运行几分钟后,刚好过了30秒,程序判断数据库连接正常,没有进行重连操作。然后过了几秒 ,我进行了数据库操作,就gone away了。也就是保险的方法还是要  需要操作数据库的时候强制重连。
在线liudianwu

只看该作者 16楼 发表于: 07-25
回 apud 的帖子
apud:用这种方法遇到的一个问题,程序运行几分钟后,刚好过了30秒,程序判断数据库连接正常,没有进行重连操作。然后过了几秒 ,我进行了数据库操作,就gone away了。也就是保险的方法还是要  需要操作数据库的时候强制重连。 (2017-07-25 09:46) 

嗯,是的,你可以采取短连接的方式进行数据库操作。每次操作数据库都是重新连接数据库,执行完后断开数据库,不过这样费时间,不建议。我的处理是一个线程实时判断是否正常,不正常则重新连接数据库,如果执行sql语句的地方执行失败,则将失败的语句存起来,等连接恢复正常后自动执行。
离线apud

只看该作者 17楼 发表于: 07-26

请教下,用你那套7色QSS样式表 制作的软件,有的时候打开出现这种情况。显示 未响应,然后自定义的界面没有显示出来。我好像很久之前偶尔碰到过一两次这种情况,软件给其它用户使用,有两个人已经反应有这个问题,但是一般 重启电脑就OK了。
离线whhitfk

只看该作者 18楼 发表于: 08-14
楼主源码开源吗? 有没有源码发一份啊  万分感谢,whhitfk@163.com
离线stlcours

只看该作者 19楼 发表于: 08-14
回 liuyuanan 的帖子
liuyuanan:多节点数据存储及同步,建议使用Redis (2017-06-18 19:38) 

有没有想关的文章可以学习一下啊??
快速回复
限100 字节
 
上一个 下一个