二 Qt之Sqlite数据库 *** 作

二 Qt之Sqlite数据库 *** 作,第1张

概述想必用Qt做界面的同学都遇到过界面卡死的问题,这里我也遇到了,我的问题出在Sqlite数据库写处理的地方,可能您会说可以将数据库写处理的 *** 作放在线程里执行啊。首先Sqlite数据库有这么一个不尽人意的特点,那就是它不支持在写数据的时候有别的 *** 作参与进来,所以无论你将写 *** 作放在自己创建的线程或是UI线程里都会有DB文件 *** 作的风险。也许您会说在写数据 *** 作时将DB连接锁起来,不让别的 *** 作来用,或者是让别

想必用Qt做界面的同学都遇到过界面卡死的问题,这里我也遇到了,我的问题出在sqlite数据库写处理的地方,可能您会说可以将数据库写处理的 *** 作放在线程里执行啊。首先sqlite数据库有这么一个不尽人意的特点,那就是它不支持在写数据的时候有别的 *** 作参与进来,所以无论你将写 *** 作放在自己创建的线程或是UI线程里都会有DB文件 *** 作的风险。也许您会说在写数据 *** 作时将DB连接锁起来,不让别的 *** 作来用,或者是让别的 *** 作等待。这样到底行不行呢?咱下面上代码:

首先说明:代码中有些变量或函数定义未给出,这里会给出它们的意思,旨在理解代码

//thread.h

#ifndefTHREAD_H

#defineTHREAD_H

#include<QThread>

classCThread:publicQThread

{

Q_OBJECT

public:

CThread(){}

protected:

voIDrun();

};

#endif

//类很简单

线程函数实现一:

//thread.cpp

#include"thread.h"

#include"sqlTbl.h"

externstd::vector<FILTERfile>g_vecStaffInfo;

voIDCThread::run()

{

QsqlDatabasensqlliteDB=QsqlDatabase::addDatabase(“QsqlITE”,“Connect”);

nsqlliteDB.setDatabasename("table.db");

nsqlliteDB.open();

if(!g_vecStaffInfo.empty()){

QsqlqueryqueryTbl(nsqlliteDB);

queryTbl.prepare("insertintotable(ID,name,salary,age)values(?,?,?)");

std::vector<STAFFINFO>::iteratoritorStaff=g_vecStaffInfo.begin();

for(;itorStaff!=g_vecStaffInfo.end();itorStaff++)

{

intiID=itorStaff->ID;

QStringstrname=ToMultiChars(itorStaff->name);

intiSalary=itorStaff->salary;

intiAge=itorStaff->age;

queryTbl.addBindValue(iID);

queryTbl.addBindValue(strname);

queryTbl.addBindValue(iSalary);

queryTbl.addBindValue(iAge);

if(!queryTbl.exec())

{

QsqlErrorerror=queryTbl.lastError();

QMessageBox::critical(0,"tableinsert",error.driverText(),QMessageBox::Ok);

return;

}

}

QsqlDatabase::database().commit();

queryTbl.finish();

}

}

其中g_vecStaffInfo是一个全局的数组,用来从上层传数据,然后通过线程将数据放进DB文件,ToMultiChars是将宽字节转为多字节的函数。

此时线程函数没有加锁,这个线程代码能不能满足不和界面查数据 *** 作产生冲突呢,经验证产生冲突的事件是几率很高的偶发性事件。不知大家知不知道原因所在。

线程函数实现二:

#include"thread.h"

#include"sqlTbl.h"

externstd::vector<FILTERfile>g_vecStaffInfo;

externqmutexg_nsqlMutex;

voIDCThread::run()

{

QsqlDatabasensqlliteDB=QsqlDatabase::addDatabase(“QsqlITE”,“Connect”);

nsqlliteDB.setDatabasename("table.db");

nsqlliteDB.open();

if(!g_vecStaffInfo.empty()){

if(g_nsqlMutex.tryLock())

g_nsqlMutex.unlock();

g_nsqlMutex.lock();

QsqlqueryqueryTbl(nsqlliteDB);

queryTbl.prepare("insertintotable(ID,QMessageBox::Ok);

return;

}

}

QsqlDatabase::database().commit();

g_nsqlMutex.unlock();

queryTbl.finish();

}

}

线程函数实现二行不行呢,这里认为queryTbl对nsqlliteDB是独占的,经测试这样是解决了DB文件访问冲突的问题,但是原始问题还是没有被解决:界面访问数据时卡死。

线程函数实现三:

#include"thread.h"

#include"sqlTbl.h"

externstd::vector<FILTERfile>g_vecStaffInfo;

externqmutexg_nsqlMutex;

voIDCThread::run()

{

QsqlDatabasensqlliteDB=QsqlDatabase::addDatabase(“QsqlITE”,“Connect”);

nsqlliteDB.setDatabasename("table.db");

nsqlliteDB.open();

if(!g_vecStaffInfo.empty()){

if(g_nsqlMutex.tryLock())

g_nsqlMutex.unlock();

else

return;

QsqlqueryqueryTbl(nsqlliteDB);

nsqlliteDB.transaction();

queryTbl.prepare("insertintotable(ID,QMessageBox::Ok);

return;

}

}

g_nsqlMutex.lock();

nsqlliteDB.commit();

g_nsqlMutex.unlock();

queryTbl.finish();

}

}

线程函数实现三同样增加了互斥,但有些不同的是,这里用到了sqlite数据库的事务,代码增加了nsqlliteDB.transaction();为什么这样呢,经过网上查找,写DB文件,像实现一和二每进行一次queryTbl.exec()都会对DB文件进行打开和关闭 *** 作一次,相当于写10000条数据打开关闭10000次,这样的写速度真是能把我们搞疯掉;而增加事务后就不同了,写10000条数据,只会在commit的时候打开关闭一次,这样的速率提升不言而喻。在commit的地方加锁,锁占的时间也在所能接受的范围之内。

这样暂时将我的问题解决了,不知道是否能给各位同行带来帮助,如果有何欠妥的地方,忘多多指教。若能给大家提供帮助,我将甚感荣幸。

转载请注明:http://blog.csdn.net/fanbiqi/article/details/40212917

总结

以上是内存溢出为你收集整理的二 Qt之Sqlite数据库 *** 作全部内容,希望文章能够帮你解决二 Qt之Sqlite数据库 *** 作所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/sjk/1171556.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-06-02
下一篇 2022-06-02

发表评论

登录后才能评论

评论列表(0条)

保存