上一篇码了下用json文件存取数据,这次换用SQLite数据库来存取,相比下更适用于大数据量和复杂操作的情况,但本文先只对存取写个示例:

首先在xxx.pro中添加SQL支持

QT += quick sql

之后在xxx.h中声明公有的save和load函数,还有私有的init函数和一个QSqlDatabase对象

#include <QVariantList>
#include <QSqlDatabase>

public:
    Q_INVOKABLE void savedata(const QVariantList &data);
    Q_INVOKABLE QVariantList loaddata();

private:
    void initdata();
    QSqlDatabase db;

一、init函数

我们先写init函数来初始化数据库

#include <QSqlQuery>
#include <QSqlDatabase>
#include <QSqlError>

void testc::initdata()
{
    db=QSqlDatabase::addDatabase("QSQLITE");    //用刚刚声明的私有成员db连接SQLITE数据库
    db.setDatabaseName("data.db");    //命名数据库文件
    if(!db.open()){    //打开数据库并检查是否成功
        qWarning()<<"打开数据库失败"<<db.lastError().text();    //若失败打印错误的文本信息
        return;
    }

    QSqlQuery query;
    QString create=R"(
        CREATE TABLE IF NOT EXISTS data(
            id INTEGER PRIMARY KEY AUTOINCREMENT,
         //键名  类型   表内主键标识  自增(每行+1)  
            num TEXT,
            city TEXT,
            people TEXT
        )
    )";
    //用R"()"包裹,语句不用""封闭和\n换行了
    if(!query.exec(create)){
        qWarning()<<"创建失败"<<query.lastError().text();
    }
}

然后在类的构造函数中调用,保证在创建对象时,数据库可用

testc::testc(QObject *parent)
    : QObject{parent}
{
    initdata();
}

但这个写法在将类反复实例化时,会有重复创建连接的问题,修正请看此篇:Qt QML连接数据库如何解决重复创建连接问题-CSDN博客

二、save函数

#include <QDebug>

void testc::savedata(const QVariantList &data)
{
    QSqlQuery cleardata("DELETE FROM data");    //清空数据(用SQL语句初始化QSqlQuery可自动执行)
    QSqlQuery insertdata;
    insertdata.prepare(R"(
        INSERT INTO data (num,city,people)
        VALUES (?,?,?)
    )");    //.prepare预编译SQL语句
    //将num,city,people填入占位符?中

    for(const QVariant& piece:data){    //用QVariant遍历QVariantList
        QVariantMap map=piece.toMap();    //将QVariant转换为QVariantMap以用键找值
        insertdata.addBindValue(map["num"]);    //取出键num对应的值map["num"]填入第一个占位符
        insertdata.addBindValue(map["city"]);
        insertdata.addBindValue(map["people"]);
        if(!insertdata.exec()){    //每次填完SQL语句就添加一次
            qWarning()<<"添加失败"<<insertdata.lastError().text();
        }
    }
    qDebug()<<"保存成功";
}

三、load函数

QVariantList testc::loaddata()
{
    QVariantList res;
    QSqlQuery query("SELECT num,city,people FROM data");    //创建读取表内键对应数据
    while(query.next()){    //.next()每次执行将指针移向下一条,创建时指针指向0
        QVariantMap map;
        map["num"]=query.value(0).toString();    //拿到query数据索引0的值,并转为字符串
        map["city"]=query.value(1).toString();
        map["people"]=query.value(2).toString();
        res.append(map);    //将QVariantMap加入QVariantList
    }
    return res;
}

四、调用

最后就是在qml中调用了,由于传入的参数和函数类型都没变,所以跟用json时是一样的,我就把上篇的直接搬过来了,就是简单的运用,具体可以看上篇的内容:

ListModel{
    id:litmodel
    ListModel{
        id:litmodel
        ListElement{
            num:""
            city:""
            people:""
        }
    }
}
Testc{
    id:test
}
Button{
    onClicked: {
        let data=[]    //创建一个万能空数组
        for(let i=0;i<litmodel.count;i++){    //遍历ListElement
            let getdata=litmodel.get(i)    //获取索引为i的ListElement数据
            data.push({
                num:getdata.num,    //num为json文件中存储的键,getdata.num为值
                city:getdata.city,
                people:getdata.people})
        }
        test.savedata(data)    //save函数存储完成
    }
}
Component.onCompleted: {
    litmodel.clear()    //清除model原有数据
    let data=test.loaddata()  
    for(let i=0;i<data.length;i++){    //遍历QVariantList
        litmodel.append(data[i])    //挨个将QVariant添加入model
    }
}

至此我们就完成了用SQLite存取ListModel数据了,逻辑其实是比json更简单的,而且对于往后的增删改查都是要方便很多的,大家可以对比选择一下

Logo

DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。

更多推荐