首页 > 数据库 >记录QT QSqlDatabase SQLite 多线程使用时报错..

记录QT QSqlDatabase SQLite 多线程使用时报错..

时间:2022-08-18 09:13:32浏览次数:80  
标签:SQLite QT database addDatabase DBHelper 线程 多线程 QSqlDatabase 链接

首先QSqlDatabase同一个实例, 不能多线程使用.

如果多线程使用,需要给每个线程创建一个QSqlDatabase实例, 一般是用Map维护各个线程实例链接, key是线程ID, value就是QSqlDatabase指针,例如:

static QMap<Qt::HANDLE,QSqlDatabase*> mapInstance;

Key(Qt::HANDLE)是: QThread::currentThreadId() 返回值, Value是: QSqlDatabase实例指针。

建议写一个全局可以使用的获取QSqlDatabase实例静态方法,例如:

class DBHelper
{
public:
    static DBHelper* GetInstance() {
        if(!databaseMap.contains(QThread::currentThreadId())) {
            databaseMap.insert(QThread::currentThreadId(), new DBHelper());
        }
        return databaseMap[QThread::currentThreadId()];
    }
    DBHelper() {
        //创建数据库链接并指定链接名称
        this->database = QSqlDatabase::addDatabase("QSQLITE", QString::number((int)QThread::currentThreadId()));
        this->database.setDatabaseName("D:/work/svnwork/ProbeTable/probe.db");
        this->database.open();//是否打开成功判断
    }

    void query(QString sql) {
        QSqlQuery sql_query(this->database);//必须指定当前数据库实例
        qDebug() << sql_query.exec(sql);//是否执行成功判断
    }
private:
    static QMap<Qt::HANDLE, DBHelper*> databaseMap;//所有数据库链接,key: 线程ID, value 数据库链接实例指针
    QSqlDatabase database;//当前线程数据库链接
};

为了更方便使用, QSqlDatabase通过DBHelper 封装了一层,添加了query方法。
需要注意的点是在通过QSqlDatabase::addDatabase函数为每个线程创建链接时,需要给每个线程分配一个连接名称:
QSqlDatabase::addDatabase("QSQLITE", QString::number((int)QThread::currentThreadId()));

这里直接用的当前线程ID当的链接名称, 不一定必须是线程ID,只要在全局中是唯一的就可以。

如果没有指定线程名称, 默认走的是QSqlDatabase内部的默认名称,也就是defaultConnection,这是addDatabase函数原型:

    static QSqlDatabase addDatabase(QSqlDriver* driver,
                                 const QString& connectionName = QLatin1String(defaultConnection));

如果在调用addDatabase的时候没有指定链接名称, 很有可能后创建的QSqlDatabase 链接覆盖掉之前的,。(因为没指定链接名称时,走的都是默认链接名称defaultConnection)。就会在第二次调用addDatabase函数时出现错误:

QSqlDatabasePrivate::removeDatabase: connection 'qt_sql_default_connection' is still in use, all queries will cease to work.
QSqlDatabasePrivate::addDatabase: duplicate connection name 'qt_sql_default_connection', old connection removed.
QSqlDatabasePrivate::database: requested database does not belong to the calling thread.
QSqlQuery::exec: database not open
SQLINFO:  QSqlError("", "Driver not loaded", "Driver not loaded")

 

最后在使用DBHelper前,声明静态变量databaseMap,像这样:

main.cpp:

QMap<Qt::HANDLE, DBHelper*> DBHelper::databaseMap;

int main(void){
  //...  
  return 0;  
}

 

标签:SQLite,QT,database,addDatabase,DBHelper,线程,多线程,QSqlDatabase,链接
From: https://www.cnblogs.com/GengMingYan/p/16597176.html

相关文章

  • 多线程.线程同步
    同步方法:synchronized同步块:synchronized(Obj){}并发:多个线程操作同一个资源队列和锁每个对象都有一个锁,sleep不会释放锁由于同一进程的多个线程共享同一块存储空间......
  • 多线程.守护线程
    daemon守护线程分为用户线程和守护线程虚拟机必须确保用户线程执行完毕虚拟机不用等待守护线程执行完毕如,后台记录操作日志,监控内存,垃圾回收等待...package......
  • 关于多线程操作单个变量进行加1问题的分析
    关于多线程操作单个变量进行加1问题的分析  摘要:在多线程的学习中,我们经常会接触到一个例子,这个例子也是一个重要的面试题,在此我详细的分析这个问题。  问题:我们现有......
  • 多线程-浅析线程安全
    多线程-共享模型之管程本文章是根据黑马JUC课程编写,记录的笔记1共享带来的问题在平常开发中,很多时候都会遇到共享数据的问题,比如售票,库存。那么如何就会引出一个疑......
  • 多线程.线程优先级
    Priority优先级线程优先级用数字表示,范围从1~10Thread.MIN_PRIORITY=1;Thread.MAX_PRIORITY=10;Thread.NORM_PRIORITY=5;使用以下方式改变或获取优先级:g......
  • 08. Qt绘图
    Qt绘图1.QPainter2D绘图离不开QPainter,可以把QPainter想象成一个画笔,开发人员拿着画笔理论上是可以绘制任何你想要的图形。QPainter一般在一个部件(widget)重绘事件(Pain......
  • [记]Rust在多线程下修改共享变量的值
    1.usestd::time::Duration;usestd::sync::{Arc,Mutex};usestd::thread;fnmain(){letokz="2333".to_string();letapple=Arc::new(Mutex::......
  • SpringBoot 多线程
    关于SpringBoot中多线程的两个注解:@Async是spring为了方便开发人员进行异步调用而出现的。在方法上加入这个注解,spring会从线程池中获取一个新的线程来执行方法,实现异步调......
  • ESP8266 安信可固件 MQTT AT指令
    9.1AT+MQTTUSERCFG-SetMQTTUserConfigSetCommand:AT+MQTTUSERCFG=<LinkID>,<scheme>,<"client_id">,<"username">,<"password">,<cert_key_ID>,<CA_ID>,<"path">A......
  • Qt Debug模式无法运行
    问题:如题,在QtCreator中使用Debug模式启动程序,直接提示“程序异常结束。”,也不报任何错,然后Debug目录直接双击xxx.exe文件,提示缺少Qt5Cored.dll解决方法:从QT的bin目录下......