Qt 中使用 QSqlLite在不同线程中的调用方法
前言
最近Qt开发应用程序时,使用到了sqllite,由于需要子线程中操作数据库,然后转到UI线程中继续操作该数据库,结果出现了意想不到的错误:
假如在线程里做了如下的操作:
QSqlDatabase db;
if (QSqlDatabase::contains("default")) {
db = QSqlDatabase::database("default");
qDebug() << "default: " << db.databaseName();
} else {
db = QSqlDatabase::addDatabase("QSQLITE", "default");
db.setDatabaseName("./data.db");
qDebug() << "addDatabase: " << db.databaseName();
}
db.open();
...
db.close();
当我们转到主线程中再次操作 sqllite 便会出现如下的报错:
QSqlDatabasePrivate::database: requested database does not belong to the calling thread.
QSqlError("", "Driver not loaded", "Driver not loaded")
在官方文档中可以找到一种解决方案如下:
在 QSqlDatabase 作用域外使用 removeDatabase 函数才是正确的做法。
把线程中的 worker 代码改写如下:
{
QSqlDatabase db;
if (QSqlDatabase::contains("default")) {
db = QSqlDatabase::database("default");
qDebug() << "default: " << db.databaseName();
} else {
db = QSqlDatabase::addDatabase("QSQLITE", "default");
db.setDatabaseName("./data.db");
qDebug() << "addDatabase: " << db.databaseName();
}
bool ok = db.open();
if (!ok) {
qDebug() << db.lastError();
} else {
qDebug() << "open database success.";
}
QSqlQuery cursor(db);
QString query;
query = R"(
CREATE TABLE IF NOT EXISTS hello (
name VARCHAR(32),
age INTERGER,
gender VARCHAR(32)
)
)";
cursor.prepare(query);
ok = cursor.exec();
if (!ok) {
qDebug() << cursor.lastError();
} else {
qDebug() << "create table hello success.";
}
// query = R"(
// INSERT INTO aimer VALUES(:name,:age,:gender)
// )";
// cursor.prepare(query);
// cursor.bindValue(":name", "shi");
// cursor.bindValue(":age", "22");
// cursor.bindValue(":gender", "male");
// ok = cursor.exec();
// if (!ok) {
// qDebug() << cursor.lastError();
// } else {
// qDebug() << "Insert data success.";
// }
cursor.prepare(R"(
delete from hello where name='shi'
)");
ok = cursor.exec();
if (!ok) {
qDebug() << cursor.lastError();
}
query = R"(
SELECT * FROM hello
)";
cursor.prepare(query);
ok = cursor.exec();
if (!ok) {
qDebug() << cursor.lastError();
} else {
while (cursor.next()) {
qDebug() << cursor.value(0).toString();
qDebug() << cursor.value(1).toString();
qDebug() << cursor.value(2).toString();
}
}
db.close();
}
QSqlDatabase::removeDatabase("default");
这样在主线程再次操作数据库就不会出现之前的错误了,运行结果如下:
addDatabase: "./data.db"
open database success.
create table hello success.
"hello world"
work is over.
open database success.
create table hello success.
Insert data success.
"shi"
"22"
"male"