You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Qt Creator中自定义Database类致SQLite驱动加载失败求助

Qt SQLite 驱动加载失败问题排查与解决

问题场景

使用Qt Creator 8.0.2开发程序,直接在MainWindow构造函数中打开SQLite数据库连接正常,但调用自定义Database类的方法时,连接失败并报错:Error open QSqlError("", "Driver not loaded", "Driver not loaded"),已排查12小时,寻求实例、指针相关的问题分析与解决方法。


可正常运行的mainwindow.cpp

#include "HeaderLibary.h"
#include "ui_mainwindow.h"
#include "mainwindow.h"

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    this->setMaximumHeight(MAX_WINDOW_HEIGHT);
    this->setMinimumHeight(MIN_WINDOW_HEIGHT);
    this->setMaximumWidth(MAX_WINDOW_WIDTH);
    this->setMinimumWidth(MIN_WINDOW_WIDTH);

    QFont font;
    font.setPixelSize(FONT_SIZE);
    font.setBold(true);
    font.setFamily(FONT_FAMILY);


    QString buffer;
    QGridLayout *windowLayout = new QGridLayout;

    matrix *inputMatrix = new matrix("input",MAXLENGTH,false,QLINEEDIT_HEIGHT,QLINEEDIT_WIDTH,font,5,5,true,1);
    inputMatrix->set_matrix();
    this->inputWidgets = inputMatrix->getMatrixWidgets();

    buffer = "Hello User, welcome to AES - Advanced Encryption Standard!";
    QLabel *title = inputMatrix->setLabel(buffer,MAX_WINDOW_WIDTH,LABEL_HIGHT);

    font.setPointSize(FONT_SIZE_TEXT);
    buffer = "With AES you can encrypt messages of up to 16 characters or 16 Bytes."
             "\n\nPlease enter your message in this matrix. One character per field in numbered order.";
    QLabel *text = inputMatrix->setLabel(buffer,MAX_WINDOW_WIDTH,LABEL_HIGHT);

    QPushButton *startBtn = inputMatrix->setButton("Start",BTN_WIDTH,BTN_HEIGHT);
    connect(startBtn,SIGNAL(clicked()),this,SLOT(start_clicked()));

    windowLayout->addWidget(title,0,0,1,2,Qt::AlignCenter);
    windowLayout->addWidget(text,1,0,1,2,Qt::AlignCenter);
    windowLayout->addLayout(inputMatrix->getLayout(),2,0,1,2,Qt::AlignCenter);
    windowLayout->addWidget(startBtn,3,1,1,1,Qt::AlignRight);


    QWidget *widget = new QWidget();
    widget->setLayout(windowLayout);
    setCentralWidget(widget);

    QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE");
    db.setDatabaseName("AES_DB.db");

    if(!db.open())
        qDebug()<< db.lastError();
}

MainWindow::~MainWindow()
{
    delete ui;
}


void MainWindow::start_clicked()
{
    QSqlDatabase db;
    QSqlQuery qry;
    QString tableName = "orginalMsgLetters";

    QString buffer= QString("DROP TABLE %1;").arg(tableName);
    if(!qry.exec(buffer))
        qDebug()<< qry.lastError();

    buffer = QString("CREATE TABLE IF NOT EXISTS %1 (id INTEGER NOT NULL PRIMARY KEY, itemValue VARCHAR(20));").arg(tableName);

    if(!qry.exec(buffer))
        qDebug()<< qry.lastError();


    bool check = false;
    int index = 0;

    while(!check){

        if(inputWidgets->at(index)->text() == ""){
            QMessageBox::information(this,tr("Error"), tr("Please fill out each box to continue"));
            return;
        }
        else if(inputWidgets->at(index)->text() == "ü" || inputWidgets->at(index)->text() == "ä" || inputWidgets->at(index)->text() == "ö" || inputWidgets->at(index)->text() == "ß"){
            QMessageBox::information(this,tr("Error"), tr("Please don't use Ü/ü, Ä/ä, Ö/ö or ß "));
            return;
        }
        else {
            if(index+1 == MAXLENGTH)
                check = true;
            else
                index++;
        }
    }

    for (int i = 0; i < MAXLENGTH; ++i) {

        buffer=QString("INSERT INTO %1 (id,itemValue)VALUES (%2,%3);").arg(tableName).arg(i).arg(this->inputWidgets->at(i)->text());

        if(!qry.exec(buffer))
            qDebug()<<qry.lastError();

        buffer=QString("SELECT * FROM %1 WHERE id=%2").arg(tableName).arg(i);
        if(!qry.exec(buffer))
            qDebug()<<qry.lastError();
        while(qry.next())
            qDebug()<< qry.value(1).toString();
     }

    db.close();
}

mainwindow.h

#pragma once

#include "HeaderLibary.h"
#include "Config_File.h"



QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE

class MainWindow : public QMainWindow
{
    Q_OBJECT

private:
    QList<QLineEdit*>* inputWidgets;
    //Database *db = new Database();

    QSqlDatabase *db = new QSqlDatabase;
    QSqlQuery *qry = new QSqlQuery;

public:
    MainWindow(QWidget *parent = nullptr);
    ~MainWindow();

private slots:
    void start_clicked();

private:
    Ui::MainWindow *ui;
};

导致错误的Database.cpp

#include "database.h"


Database::Database(){

}

Database::~Database(){
}

void Database::deleteTable(QString tableName){
    QSqlQuery qry;
    QString buffer = QString("DROP TABLE %1;").arg(tableName);
    qry.prepare(buffer);
    qry.exec();

}

void Database::connect(){
    QSqlDatabase db;
    db.addDatabase("QSQLITE");
    db.setDatabaseName("AES_DB.db");
    if(!db.open())
        qDebug()<< "Error open "<< db.lastError();
}

void Database::addValueToTable(QString tableName,int id, QString value){
    QSqlQuery qry;
    QString buffer = QString("INSERT INTO %1 (id,itemValue)VALUES (%2,%3);").arg(tableName).arg(id).arg(value);
    qry.prepare(buffer);
    if(!qry.exec()){
        qDebug()<< qry.lastError();
        qDebug()<< "\n insert Error \n";
    }

}

void Database::createTable(QString tableName){

    QSqlQuery qry;
    QString buffer = QString("CREATE TABLE IF NOT EXISTS %1 (id INTEGER NOT NULL PRIMARY KEY, itemValue VARCHAR(20));").arg(tableName);


    if(!qry.exec(buffer)){
        qDebug()<< qry.lastError();
        qDebug()<< "\n create Error \n";
    }

}

void Database::close(){

    QSqlDatabase db;
    db.close();

}

QString Database::getValueFromTable(QString tableName,int id){

    QSqlQuery qry;
    QString string = QString("SELECT * FROM %1 WHERE id=%2").arg(tableName).arg(id);
    qry.prepare(string);
    if(!qry.exec(string)){
        qDebug()<< qry.lastError();
        qDebug()<< "\n get Error \n";
    }
    while(qry.next())
        return qry.value(1).toString();

}

database.h

#pragma once

#include "Config_File.h"
#include "HeaderLibary.h"

class Database
{

private:


public:
    Database();
    ~Database();
    void connect();
    void addValueToTable(QString tableName,int id, QString value);
    void deleteTable (QString tableName);
    void createTable(QString tableName);
    QString getValueFromTable(QString tableName,int id);
    void close();
};

核心问题分析

  1. QSqlDatabase实例生命周期错误
    Database类的connect()方法中,QSqlDatabase db是局部变量,调用addDatabase后,局部变量销毁时会自动移除数据库连接,导致后续操作无有效连接。
  2. QSqlQuery未绑定有效连接
    Database类中所有QSqlQuery都是局部创建,未指定关联的数据库连接,默认使用无连接实例,引发驱动加载失败。
  3. MainWindow中错误创建QSqlDatabase指针
    QSqlDatabase *db = new QSqlDatabase;是错误用法,QSqlDatabase必须通过addDatabase静态方法创建,不能直接new。

修复方案

1. 修改Database类,保存数据库连接为成员变量

database.h

#pragma once

#include "Config_File.h"
#include "HeaderLibary.h"

class Database
{
private:
    QSqlDatabase m_db; // 成员变量保存数据库连接

public:
    Database();
    ~Database();
    bool connect(); // 返回连接状态,方便调用者判断
    void addValueToTable(QString tableName,int id, QString value);
    void deleteTable (QString tableName);
    void createTable(QString tableName);
    QString getValueFromTable(QString tableName,int id);
    void close();
};

Database.cpp

#include "database.h"

Database::Database(){
    m_db = QSqlDatabase::addDatabase("QSQLITE");
}

Database::~Database(){
    if(m_db.isOpen()){
        m_db.close();
    }
}

bool Database::connect(){
    m_db.setDatabaseName("AES_DB.db");
    if(!m_db.open()){
        qDebug()<< "Error open "<< m_db.lastError();
        return false;
    }
    return true;
}

void Database::deleteTable(QString tableName){
    QSqlQuery qry(m_db); // 绑定到成员变量的数据库连接
    QString buffer = QString("DROP TABLE %1;").arg(tableName);
    if(!qry.exec(buffer)){
        qDebug()<< qry.lastError();
    }
}

void Database::addValueToTable(QString tableName,int id, QString value){
    QSqlQuery qry(m_db);
    // 使用占位符避免SQL注入,同时解决字符串引号问题
    QString buffer = QString("INSERT INTO %1 (id,itemValue)VALUES (:id, :value);").arg(tableName);
    qry.prepare(buffer);
    qry.bindValue(":id", id);
    qry.bindValue(":value", value);
    if(!qry.exec()){
        qDebug()<< qry.lastError();
        qDebug()<< "\n insert Error \n";
    }
}

void Database::createTable(QString tableName){
    QSqlQuery qry(m_db);
    QString buffer = QString("CREATE TABLE IF NOT EXISTS %1 (id INTEGER NOT NULL PRIMARY KEY, itemValue VARCHAR(20));").arg(tableName);
    if(!qry.exec(buffer)){
        qDebug()<< qry.lastError();
        qDebug()<< "\n create Error \n";
    }
}

void Database::close(){
    if(m_db.isOpen()){
        m_db.close();
    }
}

QString Database::getValueFromTable(QString tableName,int id){
    QSqlQuery qry(m_db);
    QString string = QString("SELECT * FROM %1 WHERE id=:id").arg(tableName);
    qry.prepare(string);
    qry.bindValue(":id", id);
    if(!qry.exec()){
        qDebug()<< qry.lastError();
        qDebug()<< "\n get Error \n";
        return "";
    }
    if(qry.next()){
        return qry.value(1).toString();
    }
    return "";
}

2. 修复MainWindow类的数据库指针

mainwindow.h

#pragma once

#include "HeaderLibary.h"
#include "Config_File.h"
#include "database.h"

QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE

class MainWindow : public QMainWindow
{
    Q_OBJECT

private:
    QList<QLineEdit*>* inputWidgets;
    Database* m_db; // 使用自定义Database类

public:
    MainWindow(QWidget *parent = nullptr);
    ~MainWindow();

private slots:
    void start_clicked();

private:
    Ui::MainWindow *ui;
};

mainwindow.cpp

#include "HeaderLibary.h"
#include "ui_mainwindow.h"
#include "mainwindow.h"

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
    , m_db(new Database())
{
    ui->setupUi(this);

    this->setMaximumHeight(MAX_WINDOW_HEIGHT);
    this->setMinimumHeight(MIN_WINDOW_HEIGHT);
    this->setMaximumWidth(MAX_WINDOW_WIDTH);
    this->setMinimumWidth(MIN_WINDOW_WIDTH);

    QFont font;
    font.setPixelSize(FONT_SIZE);
    font.setBold(true);
    font.setFamily(FONT_FAMILY);


    QString buffer;
    QGridLayout *windowLayout = new QGridLayout;

    matrix *inputMatrix = new matrix("input",MAXLENGTH,false,QLINEEDIT_HEIGHT,QLINEEDIT_WIDTH,font,5,5,true,1);
    inputMatrix->set_matrix();
    this->inputWidgets = inputMatrix->getMatrixWidgets();

    buffer = "Hello User, welcome to AES - Advanced Encryption Standard!";
    QLabel *title = inputMatrix->setLabel(buffer,MAX_WINDOW_WIDTH,LABEL_HIGHT);

    font.setPointSize(FONT_SIZE_TEXT);
    buffer = "With AES you can encrypt messages of up to 16 characters or 16 Bytes."
             "\n\nPlease enter your message in this matrix. One character per field in numbered order.";
    QLabel *text = inputMatrix->setLabel(buffer,MAX_WINDOW_WIDTH,LABEL_HIGHT);

    QPushButton *startBtn = inputMatrix->setButton("Start",BTN_WIDTH,BTN_HEIGHT);
    connect(startBtn,SIGNAL(clicked()),this,SLOT(start_clicked()));

    windowLayout->addWidget(title,0,0,1,2,Qt::AlignCenter);
    windowLayout->addWidget(text,1,0,1,2,Qt::AlignCenter);
    windowLayout->addLayout(inputMatrix->getLayout(),2,0,1,2,Qt::AlignCenter);
    windowLayout->addWidget(startBtn,3,1,1,1,Qt::AlignRight);


    QWidget *widget = new QWidget();
    widget->setLayout(windowLayout);
    setCentralWidget(widget);

    if(!m_db->connect()){
        qDebug() << "数据库连接失败";
    }
}

MainWindow::~MainWindow()
{
    delete m_db;
    delete ui;
}


void MainWindow::start_clicked()
{
    QString tableName = "orginalMsgLetters";

    m_db->deleteTable(tableName);
    m_db->createTable(tableName);

    bool check = false;
    int index = 0;

    while(!check){

        if(inputWidgets->at(index)->text() == ""){
            QMessageBox::information(this,tr("Error"), tr("Please fill out each box to continue"));
            return;
        }
        else if(inputWidgets->at(index)->text() == "ü" || inputWidgets->at(index)->text() == "ä" || inputWidgets->at(index)->text() == "ö" || inputWidgets->at(index)->text() == "ß"){
            QMessageBox::information(this,tr("Error"), tr("Please don't use Ü/ü, Ä/ä, Ö/ö or ß "));
            return;
        }
        else {
            if(index+1 == MAXLENGTH)
                check = true;
            else
                index++;
        }
    }

    for (int i = 0; i < MAXLENGTH; ++i) {
        m_db->addValueToTable(tableName, i, inputWidgets->at(i)->text());
        QString value = m_db->getValueFromTable(tableName, i);
        qDebug() << value;
     }
}

额外注意事项

  • SQL注入风险:原代码直接拼接用户输入到SQL语句中,修复后使用bindValue占位符避免该问题。
  • 驱动验证:若修复后仍报错,可在程序启动时打印可用驱动:
    qDebug() << QSqlDatabase::drivers();
    
    确保输出包含QSQLITE,若缺失需检查Qt安装包是否包含SQLite驱动,或手动编译驱动。

内容的提问来源于stack exchange,提问作者Cryptos90

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.10 17:40:44