目录
一、QSqlDatabase概述
QSqlDatabase提供了一系列的接口用于访问操作数据库,包括连接数据库,输入sql语句等。
QSqlDatabase的实例表示着一个对数据库的连接。该连接通过一个受支持的数据库驱动程序(从QSqlDriver派生)提供对数据库的访问。另外,可以从QSqlDriver子类化自己的数据库驱动程序。(如何创建自己的驱动,详见其他文档)Qt支持的数据库有很多,自己首先接触到的是QODBC(用于sql server)。另外还有QSQLITE、QDB2、QIBASE、QMYSQL等。
二、QSqlDatabase模块的使用
QSqlDatabase类处理与数据库的连接,要使用这个类,头文件需要导入QSqlDatabase库:
#include <QSqlDatabase>
在qmake.pro文件中加入SQL数据库支持:
QT += sql
这个类提供了以下公共方法:QSqlDatabase::addDatabase、QSqlDatabase::removeDatabase和QSqlDatabase::database函数都是线程安全的。但是open不是线程安全的,所以在open时需要加上锁。
三、多线程操作不同的链接
1、testsqldatabase.cpp
#include "testqtdatabase.h"
#include "thread1.h"
#include "thread2.h"
#include <QSQLDatabase>
#include <QSqlQuery>
#include <QSqlError>
testqtdatabase::testqtdatabase(QWidget *parent, Qt::WFlags flags)
: QMainWindow(parent, flags)
{
ui.setupUi(this);
Thread1 *t1=new Thread1(NULL);
t1->start();
Thread2 *t2=new Thread2(NULL);
t2->start();
m_t1=t1;
m_t2=t2;
}
testqtdatabase::~testqtdatabase()
{
((Thread1*)m_t1)->setStop();
((Thread2*)m_t2)->setStop();
m_t1->wait();
m_t2->wait();
}
2、thread1.cpp
#include "thread1.h"
#include <QSqlDatabase>
#include <QSqlQuery>
#include <QSqlError>
#include <QVariant>
#include <QMutex>
QMutex g_mutex;
Thread1::Thread1(QObject *parent)
: QThread(parent)
{
m_bStop=false;
}
Thread1::~Thread1()
{
}
void Thread1::setStop()
{
m_bStop = true;
}
void Thread1::run()
{
{
QMutexLocker locker(&g_mutex);
m_db = new QSqlDatabase();
*m_db=QSqlDatabase::addDatabase("QSQLITE","test1");
QSqlDatabase & db=*m_db;
db.setDatabaseName("test.db");
bool b=db.open();
}
while(true)
{
if(m_bStop)
{
break;
}
{
QSqlQuery query(*m_db);
if(!query.exec("select * from user;"))
{
QSqlError error = query.lastError();
}
QString result="";
while(query.next()){
result+=query.value(0).toString()+' ';
result+='\n';
}
}
}
QSqlDatabase::removeDatabase("test1");
delete m_db;
}
3、thread2.cpp
#include "thread2.h"
#include <QSqlDatabase>
#include <QSqlQuery>
#include <QSqlError>
#include <QVariant>
#include <QMutex>
extern QMutex g_mutex;
Thread2::Thread2(QObject *parent)
: QThread(parent)
{
m_bStop=false;
}
Thread2::~Thread2()
{
}
void Thread2::setStop()
{
m_bStop = true;
}
void Thread2::run()
{
{
QMutexLocker locker(&g_mutex);
m_db = new QSqlDatabase();
*m_db=QSqlDatabase::addDatabase("QSQLITE","test2");
m_db->setDatabaseName("test.db");
bool b=m_db->open();
}
while(true)
{
if(m_bStop)
break;
{
QSqlQuery query(*m_db);
if(!query.exec("select * from user;"))
{
QSqlError error = query.lastError();
}
QString result="";
while(query.next()){
result+=query.value(0).toString()+' ';
result+='\n';
}
}
}
QSqlDatabase::removeDatabase("test2");
delete m_db;
}
四、总结
Sqlite数据库是支持多线程读的,但是只支持一个线程写,所以如果要进行多线程读写的话,还需要加上读写锁。open函数不是线程安全的,所以要加锁,如果不加的话有时会崩溃的。