Qt6 QML如何用SQLite数据库存储读取ListModel数据(解决重复创建连接问题)
·
上一篇码了下用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更简单的,而且对于往后的增删改查都是要方便很多的,大家可以对比选择一下
DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。
更多推荐


所有评论(0)