Qt对数据库的简单操作

1.问:数据库的操作一般是指什么?
答:我觉得任何一门语言对数据库的简单操作无非就是增、删、查、改等,入门一般都是使用SQL语句来操作数据库,当然使用SQL语句操作数据库的一大弊端就是,如果数据量大的话就会造成时间成本的剧增(如果使用单线程的话还会造成界面的卡死如果有界面的话);所以对于数据量大的存储,我觉得如果不使用多线程的话,尽量使用存储过程实现对数据库的操作。
2.问:Qt对数据库怎么操作?
答:这里只讲述简单的操作,所以我使用的也是SQL语句,而在项目中一般都会讲究mvc的思想,没有mvc的思想,自己写的代码两个月后来看只有一种感觉,我靠,这是谁写的代码,这么烂。而你自己也看不懂自己的代码,C++中类的出现使我们能够更好的管理我们的代码,写出复用性强,功能明确,分工也很明确的代码,因此,在这里,我也是将对数据库的操作封装成类,在以后使用的过程中,只是简单的copy几个文件的问题,再修改一下数据库表中的字段就很容易的实现了,节省大量的时间。
3.问:具体的实现?
答:先讲一下结构,我是将对数据库的操作单独封装成类,将读表和写表的过程再分别封装成类,这样就会很明确自己的步骤。并可以通过读配置文件的信息对数据库进行设置。看一下具体实现吧。
首先是对数据库设置名称,写代码写注释是一个很好的习惯,不要让别人看不懂你的代码。。
首先看看数据库表结构,我这里是操作了多张表
【Qt对数据库的简单操作】_rowid | FileName | FilePath | FileType | FileSize | FileTime |
1 | test.txt | C:\text | 文件 | 20 kb | 2106-12-17 10:21:56 |
2 | test.ini | D:\workspace\test | 文件 | 58 kb | 2106-12-17 10:21:56 |
3 | work | D:\workspace\test | 文件夹 | 0 kb | 2106-12-17 10:21:56 |
定义一些可以用到的变量

QSqlDatabase *pDb; QSqlQuery *pQuery; //连接名 QString connName; //数据库文件 QString fileDb;

/******************************************* * creator: @ji * function: 设置数据库名称 * Date: 2016-09-13 * parameter: 数据库名称 ********************************************/ bool QDBHelpe::setDBName(QString str_DBName) { try{ fileDb = str_DBName; return true; } catch(...) { return false; } }

接下来解释千篇一律的打开数据库,关闭数据库等等。。
/******************************************* * creator: @ji * function: 打开数据库连接 * Date: 2016-09-13 * parameter: ********************************************/ int QDBHelpe::openDB() { try { if (pDb) { closeDB(); } pDb = new QSqlDatabase(); //防止重复打开同名连接 if(QSqlDatabase::contains(connName)) *pDb = QSqlDatabase::database(connName); else *pDb = QSqlDatabase::addDatabase("QSQLITE", connName); pDb->setDatabaseName(fileDb); if (pDb->open()) { if (pQuery) { delete pQuery; pQuery = NULL; } pQuery = new QSqlQuery(*pDb); return 0; } return -1; } catch (...) { return -1; } } /******************************************* * creator: @ji * function: 关闭数据库连接 * Date: 2016-09-13 * parameter: 串口信息 ********************************************/ void QDBHelpe::closeDB() { try { if (pQuery) { delete pQuery; pQuery = NULL; } if (pDb && pDb->isOpen()) { pDb->close(); delete pDb; pDb = NULL; } //从列表中移除连接 QSqlDatabase::removeDatabase(connName); } catch (...) {} } /******************************************* * creator: @ji * function: 执行sql语句 * Date: 2016-09-13 * parameter: 需要执行的sql语句 ********************************************/ bool QDBHelpe::executeSql(QString sql) { try { openDB(); QSqlQuery q(*pDb); bool ret = q.exec(sql); closeDB(); qDebug()<<"ret = "<

反序列化和序列化就是将表中的字段值和QString字符串的相互转换。
读表的过程通常需要是将表里面的某一些数据全部读出来,所以我这里实现了获取表中的多行数据,单行数据的获取我没有实现,如果需要,可以自行实现。
/******************************************* * creator: @ji * function: 获取表单数据列表 * Date: 2016-09-13 * parameter: 数据库查询条件数据库名 *******************************************/ QList* sQLReadHelp::getList(QString strWhere,QString strTableName) { QSqlQuery* query = NULL; QList* pCheckList = new QList(); if (strWhere.trimmed() != "") { strWhere = " where " + strWhere; } try { QString sql = QString("select * from %1 %2") .arg(strTableName) .arg(strWhere); int num = 0; query = g_pQDBHeper->getDataSet(sql, &num); for (int i=0; i < num; i++) { sQLReadHelp *pWrite = getModel(*query); if(pWrite != NULL) { pCheckList->append(pWrite); } } g_pQDBHeper->closeDB(); return pCheckList; } catch(...) { if (query) { g_pQDBHeper->closeDB(); query = NULL; } if (pCheckList) { //释放内部QcPlan指针 qDeleteAll(*pCheckList); pCheckList->clear(); delete pCheckList; } } return NULL; }

而获取列表的前提是获取一行数据,
/******************************************* * creator: @ji * function: 获取一个对象实体 * Date: 2016-09-13 * parameter: 表单获取数据集指针 *******************************************/ sQLReadHelp* sQLReadHelp::getModel(QSqlQuery& query) { sQLReadHelp *pWrite = NULL; try { if (query.next()) { pWrite = new sQLReadHelp(); pWrite->m_FileName = query.value("FileName").toString(); pWrite->m_FilePath = query.value("FilePath").toString(); pWrite->m_FileType = query.value("FileType").toString(); pWrite->m_FileSize = query.value("FileSize").toString(); pWrite->m_FileTime = query.value("FileTime").toString(); return pWrite; } return NULL; } catch(...) { if (pWrite) delete pWrite; return NULL; } }

至此,对于表的读操作基本已经完成
5.问:那么写表呢?
答:写表和读表的过程基本是一样的,看看具体实现吧。
/**************************sQLWriteHelp.h*************************************/ class sQLWriteHelp { public: sQLWriteHelp(); /**具体的函数会在cpp文件中讲到*/ public: /**这些字段对应表中的字段*/ QString m_FileName; QString m_FilePath; QString m_FileType; QString m_FileSize; QString m_FileTime; private: QString m_TableName; };

序列化和反序列和读表的一模一样,这里就不在啰嗦了;获取更新表单和插入表单的SQL语句,说简单点就是一个重组SQL语句的过程。
/******************************************* * creator: @ji * function: 获取更新表单sql语句 * Date: 2016-09-13 * parameter: 数据类指针 sql查询条件 *******************************************/ QString sQLWriteHelp::getUpdateStr(sQLWriteHelp* p, QString strWhere) { QString sql = QString("update %1 set ").arg(m_TableName); sql += "FileName='" + p->m_FileName + "',"; sql += "FilePath='" + p->m_FilePath + "',"; sql += "FileType='" + p->m_FileType + "',"; sql += "FileSize='" + p->m_FileSize + "',"; sql += "FileTime='" + p->m_FileTime + "'"; if (strWhere != "") sql += " where " + strWhere; else sql += " where FileName='" + p->m_FileName + "'"; return sql; }

/******************************************* * creator: @ji * function: 获取插入表单sql语句 * Date: 2016-09-13 * parameter: 数据类指针 sql查询条件 *******************************************/ QString sQLWriteHelp::getInsertStr(sQLWriteHelp* p) { QString sql = QString("insert into %1 (FileName,FilePath,FileType,FileSize,FileTime) values (") .arg(m_TableName); sql += "'" + p->m_FileName + "',"; sql += "'" + p->m_FilePath + "',"; sql += "'" + p->m_FileType + "',"; sql += "'" + p->m_FileSize + "',"; sql += "'" + p->m_FileTime + "'"; sql += ")"; return sql; }

判断表单是否存在某条记录,可以根据自己的需求选择是一个条件还是多个条件,我这里是因为同名文件可能存在于不同的文件夹,所以选择了判断两个字段。
/******************************************* * creator: @ji * function: 判断表单是否存在记录 * Date: 2016-09-13 * parameter: 查询条件 *******************************************/ bool sQLWriteHelp::exist(QString strFileName,QString strFilePath) { try { QString strSql = QString("select count(1) from %1 where FileName='%2' and FilePath='%3'") .arg(m_TableName).arg(strFileName).arg(strFilePath); QSqlQuery *pQuery = g_pQDBHeper->getDataSet(C_STR(strSql), NULL); bool ret = false; if (pQuery->next()) { ret = (pQuery->value(0).toInt() > 0) ? true : false; } g_pQDBHeper->closeDB(); return ret; } catch (...) { return false; } }

表单增加一个数据就是传入一个数据指针再解析的过程,然后插入数据库
/******************************************* * creator: @ji * function: 表单增加一条数据 * Date: 2016-09-13 * parameter: 数据类指针表名称 *******************************************/ bool sQLWriteHelp::add(sQLWriteHelp* model,QString strTableName) { try { this->setTableName(strTableName); QString strwhere; strwhere = ""; if (exist(model->m_FileName,model->m_FilePath)) { update(model,strwhere); return true; } QString sql = getInsertStr(model); return g_pQDBHeper->executeSql(sql); } catch (...) { return false; } }

/******************************************* * creator: @ji * function: 表单更新数据 * Date: 2016-09-13 * parameter: 数据类指针 sql查询条件 *******************************************/ bool sQLWriteHelp::update(sQLWriteHelp* model, QString strWhere) { try { QString sql = getUpdateStr(model,strWhere); return g_pQDBHeper->executeSql(sql); } catch(...) { return false; } }

清空一张表,因为我这里表里面设置了第一列行号的自增功能,所以清空后需要将语气关联的记录该表行号的另一张表数据置0操作。
/******************************************* * creator: @ji * function: 清空一张表数据 * Date: 2016-12-08 * parameter: 表名称 *******************************************/ bool sQLWriteHelp::deleteTableAllData(QString strTableName) { QString sql = QString("delete from %1").arg(strTableName); g_pQDBHeper->executeSql(sql); QString sql2 = QString("update sqlite_sequence SET seq = 0 where name ='%1'").arg(strTableName); return g_pQDBHeper->executeSql(sql2); }

/******************************************* * creator: @ji * function: 将一张表的数据完全覆盖另一张表 * Date: 2016-12-08 * parameter: 表名称 *******************************************/ bool sQLWriteHelp::copyTB2ToTB1(QString strTableName1,QString strTableName2) { QString sql = QString("insert into %1 select * from %2").arg(strTableName1).arg(strTableName2); return g_pQDBHeper->executeSql(sql); }

6.问:封装好之后我们需要怎么具体的调用?
答:所以接下来我就要简单的讲讲具体的调用方法,首先看看插入数据
/**首先new一个写表的指针出来**/ sQLWriteHelp *model = new sQLWriteHelp(); /**接下来解释将数据赋值给指针的每一项**/ model->m_FileName = QString("生在90后的60后的专栏.ini"); model->m_FilePath = QSting("C:\xxx\xxx"); model->m_FileType = QString("文件"); model->m_FileSize = QString::number(520) + "kb"; model->m_FileTime = QString("2016-12-17"); /**调用插入标的函数就可以了**/ g_pSQLwriteHelp->add(model,m_strTableName);

从数据库获取列表
/******************************************************** * creator: @ji * function: 从数据库中获取文件列表 * Date: 2016-12-08 * parameter: * ******************************************************/ QList* FileSerch::getFileList(QString sql,QString strTableName) { QList* m_pCheckList; m_pCheckList = g_pSQLreadHelp->getList(sql,strTableName); return m_pCheckList; }

至此,Qt对数据库的简单操作基本就已经完成了,欢迎大家交流学习,分享就是进步。。。

    推荐阅读