Qt数据库应用10-通用数据库设置
一、前言
做过了众多的项目,只要是用了数据库的项目,基本上还有一个需求就是,提供一个界面用来初始化数据库,相当于恢复出厂设置的数据,一般恢复出厂设置需要复位的是配置文件、数据库文件、布局文件这几种,其中配置文件和布局文件都可以通过先删除原来的文件,然后重新生成新的默认文件来实现,而数据库文件只有sqlite才是文件型的数据库,也可以采用类似方式,比如将出厂设置的数据库文件放在资源文件,需要恢复的时候,先删除原来的文件,然后从资源文件拷贝出来对应的文件即可,同时还要赋值可读写权限。
数据库恢复出厂,还有一种更好的办法就是通过执行sql语句去实现,这种办法通用各种数据库,比如sqlite、mysql、posggres等,都可以通过执行sql语句的方式,新建数据库以及重置数据库表,基本上的流程都是:删除数据库(有些不能通过删除数据库形式的则删除数据库表)、新建数据库、新建数据库表、添加初始数据。经过这几个步骤以后,就会生成一个全新的干干净净的按照自己要求的数据库。有些时候,我们不想去挨个界面中删除清空数据,直接来个恢复出厂,清清爽爽干干净净的一步到位。
既然是通用的数据库设置,那当然需要支持多种数据库了,整个轮子组件还是花了点心思的,完善了很多年,在各种项目中验证和迭代,形成现在的规范。数据库的相关参数就几个:数据库类型、数据库地址、数据库端口、数据库名称、数据库用户名称、数据库用户密码、其中数据库地址既可以填网址也可以填IP地址。这些参数可以直接在界面上选择,选择好以后存储到配置文件,同时还提供检测连接功能,测试下填入的信息是否正确,默认还可以自动填入数据库的端口,比如mysql是3306,sqlserver是1433。
二、功能特点
- 同时支持多种数据库比如odbc、sqlite、mysql、postgresql、sqlserver、oracle、人大金仓等。
- 一个数据库类即可管理本地数据库通信,也支持远程数据库通信等。
- 数据库线程支持执行各种sql语句,包括单条和批量。
- 组件中的所有类打印信息、错误信息、执行结果都信号发出去。
- 集成数据库通用翻页类(负责具体处理逻辑),搭配分页导航控件(负责外观),形成超级牛逼的翻页控件。
- 集成数据库自动清理类,设定最大记录数后台自动清理早期数据。
- 集成自定义委托类,支持复选框、文本框、下拉框、日期框、微调框、进度条等。
- 同时支持Qt4-Qt6,亲测Qt4.6到Qt6.1任意版本,任意系统和编译器。
- 本组件无故障 360天7乘24小时 运行在至少上万个现场,商业级别品质保证。
- 每个类都对应完整详细的使用示例,注释详细,非常适合阅读学习。
- 可以作为独立的程序运行,比如自动清理早期数据,同步数据到云端。
- 全部线程处理,不卡界面,自动重连数据库。
- 普通测试情况,sqlite数据库,数据库发生器每秒钟插入1000条记录约0.003秒钟,同时自动清理数据类每秒钟删除1000条记录约0.13秒,不同线程互不干扰。
三、体验地址
- 体验地址:https://pan.baidu.com/s/1ZxG-oyUKe286LPMPxOrO2A 提取码:o05q 文件名:bin_dbtool.zip
- 国内站点:https://gitee.com/feiyangqingyun
- 国际站点:https://github.com/feiyangqingyun
- 个人主页:https://blog.csdn.net/feiyangqingyun
- 知乎主页:https://www.zhihu.com/people/feiyangqingyun/
四、效果图

五、相关代码
void frmConfigDb::on_btnConnect_clicked()
{
{
DbInfo dbInfo;
dbInfo.connName = connName;
dbInfo.dbName = AppConfig::LocalDbName;
dbInfo.hostName = AppConfig::LocalHostName;
dbInfo.hostPort = AppConfig::LocalHostPort;
dbInfo.userName = AppConfig::LocalUserName;
dbInfo.userPwd = AppConfig::LocalUserPwd;
QString dbType = AppConfig::LocalDbType.toUpper();
if (dbType == "SQLITE") {
dbInfo.dbName = DbHelper::getDbDefaultFile(connFlag);
if (QFile(dbInfo.dbName).size() <= 4) {
QUIHelper::showMessageBoxError("数据库文件不存在!", 5);
return;
}
}
QSqlDatabase database;
if (DbHelper::initDatabase(true, dbType, database, dbInfo)) {
if (database.open()) {
database.close();
QUIHelper::showMessageBoxInfo("打开数据库成功!", 3);
} else {
QString error = database.lastError().text();
QUIHelper::showMessageBoxError("打开数据库失败!\n" + error, 3);
}
} else {
QString error = database.lastError().text();
QUIHelper::showMessageBoxError("连接数据库失败!\n" + error, 3);
}
}
QSqlDatabase::removeDatabase(connName);
}
void frmConfigDb::on_btnInit_clicked()
{
QString sqlName = QString("%1/db/%2.sql").arg(QUIHelper::appPath()).arg(connFlag);
QFile file(sqlName);
if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
QUIHelper::showMessageBoxError("数据库脚本文件打开失败!", 3);
return;
}
QElapsedTimer time;
time.start();
{
DbInfo dbInfo;
dbInfo.connName = connName;
dbInfo.dbName = AppConfig::LocalDbName;
dbInfo.hostName = AppConfig::LocalHostName;
dbInfo.hostPort = AppConfig::LocalHostPort;
dbInfo.userName = AppConfig::LocalUserName;
dbInfo.userPwd = AppConfig::LocalUserPwd;
QString dbType = AppConfig::LocalDbType.toUpper();
if (dbType == "SQLITE") {
dbInfo.dbName = DbHelper::getDbDefaultFile(connFlag);
//如果文件存在则先删除原来的数据库文件,貌似win上不行
QFile file(dbInfo.dbName);
if (file.exists()) {
bool ok = file.remove();
if (!ok) {
qDebug() << TIMEMS << "remove error" << dbInfo.dbName;
}
//清空所有表
QStringList tables = QSqlDatabase::database().tables();
foreach (QString table, tables) {
DbHelper::clearTable(table, dbType);
qDebug() << TIMEMS << "clearTable" << table;
}
//关闭默认数据库连接
QSqlDatabase::database().close();
}
}
//初始化数据库连接并打开数据库
QSqlDatabase database;
if (!DbHelper::initDatabase(true, dbType, database, dbInfo)) {
QString error = database.lastError().text();
QUIHelper::showMessageBoxError("连接数据库失败!\n" + error, 3);
return;
}
if (!database.open()) {
QString error = database.lastError().text();
QUIHelper::showMessageBoxError("打开数据库失败!\n" + error, 3);
return;
}
QSqlQuery query(QSqlDatabase::database(connName));
//第一步:删除原有数据库
QString sql = QString("DROP DATABASE %1;").arg(dbInfo.dbName);
qDebug() << TIMEMS << "sql:" << sql << "result:" << query.exec(sql);
//第二步:新建数据库
sql = QString("CREATE DATABASE %1;").arg(dbInfo.dbName);
qDebug() << TIMEMS << "sql:" << sql << "result:" << query.exec(sql);
//第三步:切换到新建的数据库库并执行建表语句
database.close();
if (!DbHelper::initDatabase(false, dbType, database, dbInfo)) {
QString error = database.lastError().text();
QUIHelper::showMessageBoxError("连接数据库失败!\n" + error, 3);
return;
}
if (!database.open()) {
QString error = database.lastError().text();
QUIHelper::showMessageBoxError("打开数据库失败!\n" + error, 3);
return;
}
//将执行出错的sql语句输出到文件方便查看
QString fileName2 = QString("%1/db/error.sql").arg(QUIHelper::appPath());
QFile file2(fileName2);
QSqlQuery query2(QSqlDatabase::database(connName));
sql = "BEGIN;";
qDebug() << TIMEMS << "sql:" << sql << "result:" << query2.exec(sql);
while (!file.atEnd()) {
sql = QString::fromUtf8(file.readLine());
sql.replace("\n", "");
//有些数据库不支持的语句跳过去
if (DbHelper::existNoSupportSql(sql)) {
continue;
}
//重新纠正sql语句
DbHelper::checkSql(dbType, sql);
if (!query2.exec(sql)) {
//打印及输出错误信息
QString error = query2.lastError().text();
qDebug() << TIMEMS << "sql:" << sql << error;
//没打开则先打开
if (!file2.isOpen()) {
file2.open(QFile::WriteOnly | QFile::Append);
}
QString msg = QString("时间[%1] 语句: %2 错误: %3\n").arg(DATETIME).arg(sql).arg(error);
file2.write(msg.toUtf8());
}
}
sql = "COMMIT;";
qDebug() << TIMEMS << "sql:" << sql << "result:" << query2.exec(sql);
database.close();
//sqlite数据库的话再执行下压缩减少体积
if (dbType == "SQLITE") {
DbHelper::execSql("VACUUM;");
}
}
QSqlDatabase::removeDatabase(connName);
double ms = time.elapsed();
QString info = QString("数据库脚本执行成功,总共用时 %1 秒!\n记得重新启动程序!").arg(QString::number(ms / 1000, 'f', 1));
QUIHelper::showMessageBoxInfo(info, 3);
}
Qt数据库应用10-通用数据库设置的更多相关文章
- DB2通用数据库性能调整的常用方法
DB2通用数据库性能调整的常用方法 DB2通用数据库性能调整的常用方法 Agenda 统计值更新--runstats 调整Buffer pool 调整日志缓冲区大小 应用程序堆大小 排序堆大小 ...
- php大力力 [020节]mysql数据库唯一id字段如何设置
2015-08-26 php大力力020.mysql数据库唯一id字段如何设置 不懂 以下有些文章 mysql唯一id 自动生成 uuid mysql 里面可以用uuid()语句来生成一个UUID:s ...
- 一个通用数据库访问类(C#,SqlClient)
本文转自:http://www.7139.com/jsxy/cxsj/c/200607/114291.html使用ADO.NET时,每次数据库操作都要设置connection属性.建立connecti ...
- SQL Server中通用数据库角色权限处理
SQL Server中通用数据库角色权限处理 最近和同事在做数据库权限清理的事情,主要是删除一些账号:取消一些账号的较大的权限等,例如,有一些有db_owner权限,我们取消账号的数据库角色db_ ...
- C# 通用数据库配置界面,微软原生DLL重整合
C# 通用数据库配置界面,微软原生DLL重整合 自己整合了 微软自带的数据连接配置界面对话库 Microsoft.Data.ConnectionUI.Dialog.dll 微软自带的数据连接配 ...
- Oracle数据库版本10.2.0.1升级到10.2.0.3(转)
Oracle数据库版本10.2.0.1升级到10.2.0.3 1.停止OEM/isqlplus/监听/DB实例 $ emctl stop dbconsole $ isqlplusctl stop $ ...
- [转]DbHelper通用数据库访问帮助类
之前我一直都是在博客园中查看各位高手的博文,确实学到了不少知识,不过比较少写博客,现在就把我自己在项目实施过程中使用到比较好的技术框架写出来,希望能让更多的人了解和学习. 通常我们在开发使用数据库访问 ...
- 用Java实现异构数据库的高效通用分页查询功能
不同数据库的分页查询语句有着较大区别,其中MySQL数据的limit offset语法最为简单,而SQL Server数据库和Oracle数据库的分页就比较复杂了. 网上常见的SQL Server和O ...
- SQL Server中通用数据库角色权限的处理详解
SQL Server中通用数据库角色权限的处理详解 前言 安全性是所有数据库管理系统的一个重要特征.理解安全性问题是理解数据库管理系统安全性机制的前提. 最近和同事在做数据库权限清理的事情,主要是删除 ...
- MySQL数据库的10大经典错误案例
学习任何一门技术的同时,其实就是自我修炼的过程.沉下心,尝试去拥抱数据的世界! 案例一 Too many connections (连接数过多,导致连接不上数据库,业务无法正常进行) 问题还原: 解决 ...
随机推荐
- python中的内置函数zip函数
关于zip()函数,有几点要讲的. 首先,官方文档中,它是这样描述的: Make an iterator that aggregates elements from each of the itera ...
- Tarjan 算法
远古算法笔记. dfs 生成树 无向图 对于一张连通的无向图,我们可以从任意一点开始 dfs,得到原图的一棵生成树(以开始 dfs 的那个点为根). 这棵生成树上的边称作树边,不在生成树上的边称作非树 ...
- 云原生周刊:K8sGPT 加入 CNCF | 2024.1.8
开源项目推荐 VolSync VolSync 使用 rsync 或 rclone 在集群之间异步复制 Kubernetes 持久卷.它还支持通过 Restic 创建持久卷的备份. KubeClarit ...
- C++版的Mc
非常垃圾的c++版Mc. #include<bits/stdc++.h> #include<windows.h> #include<conio.h> using n ...
- python之图片与视频互转
图片转视频 def image_to_video(image_dir, video_dir, fps): im_list = [i for i in os.listdir(image_dir) if ...
- python接口自动化框架-case依赖与SQL依赖以及SQL断言实现
框架目录: 整体思路: 采用excle数据驱动维护用例,数据依赖:两种实现方法case依赖与sql依赖,优先使用case依赖, 最终运行的用例是: 维护用例在datacase目录下: 涉及到用例信息新 ...
- Go下载依赖包失败的解决方法
jenkins构建job,执行go test命令报如下图的timeout错误 从报错信息中可以看出是因为下载依赖包超时 解决方法: go env查看go环境变量 GOSUMDB=sum.golang. ...
- 面试:靠着这篇笔记,我拿下了16k车载测试offer!
如何写简历个人技能个人技能一般不要超过10条,一般在8条内. 一.测试流程和技术 1.熟悉车载系统研发和测试流程,能独立编写各种测试文档. 2.熟悉车载系统测试用例设计思路,能独立编写仪表和车机的测试 ...
- "(UE4Editor.exe中)处有未经处理的异常:0xC0000005:读取位置0x0000000000000000时发生访问冲突"报错情况+解决方法+原因分析
报错情况:使用ue4.27 Slate编写Widget时想通过获取Worl(通过本地PlayerController获取)来实现"设置定时任务为在音乐结束后自动触发函数"的功能 p ...
- Abp vNext 入门到放弃系列
文章目录 1.模块介绍 2.模块加载机制 3.依赖注入 4.AutoMapper-- 待定 5.本地化--待定 6.模型验证--待定 7.异常处理--待定 8.缓存 9.动态代理和拦截 10.分布式锁 ...